TCP并发实现

文章目录

TCP服务端

基础服务端

c 复制代码
// 基础TCP服务器核心流程
#define BUFFER_SIZE 1024  // 根据设备内存自定义
char buf[BUFFER_SIZE];

int main() {
    // 1. 创建socket
    fd = socket(AF_INET, SOCK_STREAM, 0);
    
    // 2. 准备地址结构
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = 0;  // INADDR_ANY的另一种写法
    
    // 3. 绑定地址
    bind(fd, (struct sockaddr *)&addr, sizeof(addr));
    
    // 4. 开始监听
    listen(fd, BACKLOG);
    
    // 5. 接受连接(阻塞等待)
    newfd = accept(fd, NULL, NULL);  // 不关心客户端地址
    
    // 6. 接收数据
    read(newfd, buf, BUFFER_SIZE);
    
    // 7. 关闭连接
    close(newfd);
    close(fd);
    return 0;
}

TCP服务设计模式

迭代服务(一次处理一个客户端)

c 复制代码
// 简化的迭代服务器框架
while (1) {
    client_fd = accept(server_fd, NULL, NULL);
    if (client_fd < 0) continue;
    
    handle_client(client_fd);  // 处理客户端请求
    
    close(client_fd);  // 处理完后关闭
}

缺点:无法并发处理多个客户端

多进程并发服务

c 复制代码
// 父进程:监听连接,创建子进程处理
// 子进程:处理具体客户端请求,结束后退出

pid_t pid = fork();
if (pid == 0) {
    // 子进程
    close(server_fd);  // 关闭不需要的监听socket
    handle_client(client_fd);
    close(client_fd);
    exit(0);  // 子进程结束
} else {
    // 父进程
    close(client_fd);  // 父进程关闭已分发的客户端socket
    waitpid(-1, NULL, WNOHANG);  // 非阻塞回收子进程
}
僵尸进程处理(信号处理)
c 复制代码
// 使用信号处理函数回收子进程
void sigchld_handler(int sig) {
    while (waitpid(-1, NULL, WNOHANG) > 0) {
        // 回收所有已终止的子进程
    }
}

// 注册信号处理器
signal(SIGCHLD, sigchld_handler);

// 更推荐使用sigaction(可重启系统调用)
struct sigaction sa;
sa.sa_handler = sigchld_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
sigaction(SIGCHLD, &sa, NULL);

多线程并发服务

c 复制代码
// 主线程:监听连接,创建子线程
// 工作线程:处理客户端请求

void *client_handler(void *arg) {
    int client_fd = *(int *)arg;
    // 处理客户端...
    close(client_fd);
    return NULL;
}

// 创建线程处理每个客户端
pthread_t tid;
int *client_fd_ptr = malloc(sizeof(int));
*client_fd_ptr = client_fd;
pthread_create(&tid, NULL, client_handler, client_fd_ptr);
pthread_detach(tid);  // 分离线程,自动回收资源
嵌入式设备线程注意
c 复制代码
// 1. 设置线程栈大小(嵌入式内存有限)
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 8192);  // 8KB栈空间

// 2. 线程池模式(避免频繁创建销毁线程)
// 3. 注意线程安全,共享数据加锁

TCP客户端

基础客户端

c 复制代码
// 核心流程
int main() {
    // 1. 创建socket
    fd = socket(AF_INET, SOCK_STREAM, 0);
    
    // 2. 设置服务器地址
    addr.sin_family = AF_INET;
    addr.sin_port = htons(PORT);
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    // 3. 连接服务器
    connect(fd, (struct sockaddr *)&addr, sizeof(addr));
    
    // 4. 发送数据
    write(fd, STR, sizeof(STR));
    
    // 5. 关闭连接
    close(fd);
}

交互式客户端

c 复制代码
// 支持命令行参数和交互式输入
int main(int argc, char *argv[]) {
    // 检查参数
    if (argc < 3) {
        fprintf(stderr, "用法: %s <IP地址> <端口>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    
    // 解析参数
    char *server_ip = argv[1];
    int server_port = atoi(argv[2]);
    
    // 创建socket和连接...
    
    // 交互循环
    while (1) {
        printf("请输入消息: ");
        fgets(buf, BUFSIZ, stdin);
        
        // 发送数据
        int n = write(fd, buf, strlen(buf));
        if (n <= 0) {
            perror("发送失败");
            break;
        }
        
        // 可选:接收服务器响应
        // n = read(fd, response, sizeof(response));
    }
}

客户端断线重连机制

c 复制代码
// 嵌入式设备常用,增加连接稳定性
#define MAX_RETRY 5
#define RETRY_DELAY 3  // 秒

int connect_with_retry(const char *ip, int port, int max_retry) {
    int sockfd;
    struct sockaddr_in addr;
    
    for (int retry = 0; retry < max_retry; retry++) {
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) {
            perror("创建socket失败");
            return -1;
        }
        
        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        inet_pton(AF_INET, ip, &addr.sin_addr);
        
        if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == 0) {
            printf("连接成功(第%d次尝试)\n", retry + 1);
            return sockfd;
        }
        
        close(sockfd);
        printf("连接失败,%d秒后重试...\n", RETRY_DELAY);
        sleep(RETRY_DELAY);
    } 
    
    fprintf(stderr, "连接失败,达到最大重试次数\n");
    return -1;
}
相关推荐
步步为营DotNet4 小时前
深度剖析.NET中IHostedService:后台服务管理的关键组件
服务器·网络·.net
Ares-Wang4 小时前
网络》》路由引入 、路由控制 》》路由策略 route-policy 、Filter-Policy(过滤策略)
网络·智能路由器
Jia ming5 小时前
虚拟地址与物理地址:64位VS48位
网络
Ghost Face...5 小时前
i386 CPU页式存储管理深度解析
java·linux·服务器
的卢马飞快6 小时前
【C语言进阶】给数据一个“家”:从零开始掌握文件操作
c语言·网络·数据库
Yu_Lijing6 小时前
《图解HTTP》笔记与读后感(上)
网络·笔记·网络协议·http
czy87874756 小时前
connect() 的阻塞特性取决于它所关联的 socket 是否被设置为非阻塞模式,connect() 会等待 TCP 三次握手的超时时间
服务器·网络·tcp/ip
geshifei7 小时前
Sched ext回调2——enable(linux 6.15.7)
linux·运维·服务器
上海云盾-小余7 小时前
Edge SCDN是如何实现智能 WAF 防护的?
前端·网络·安全·edge
傻啦嘿哟8 小时前
Python批量重命名照片并按拍摄日期归类:从原理到实践
linux·运维·服务器