CMS8S6990串口协议设计:帧格式、校验与状态机避坑指南
2026/10/15 19:01:23
在网络编程中,为了提高服务器的并发处理能力,我们通常需要使用多线程技术。本文将详细介绍如何将传统的单线程服务器改造为多线程版本,并通过完整的代码示例展示实现过程。
多线程服务器的核心思想是:
这种设计可以让服务器同时处理多个客户端请求,大大提高并发性能。
首先,我们需要定义一个结构体来封装客户端的连接信息:
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<pthread.h>#include<arpa/inet.h>#include<sys/socket.h>#include<errno.h>#defineMAX_CLIENTS1024#defineBUFFER_SIZE1024#definePORT8888// 客户端信息结构体structSockInfo{intfd;// 客户端文件描述符structsockaddr_inaddr;// 客户端地址信息};关键点说明:
fd初始化为 -1 表示该位置可用// 全局客户端信息数组structSockInfoclients[MAX_CLIENTS];// 初始化客户端数组voidinit_clients(){for(inti=0;i<MAX_CLIENTS;i++){clients[i].fd=-1;// -1 表示该位置可用memset(&clients[i].addr,0,sizeof(structsockaddr_in));}}为什么初始化为 -1?
// 子线程处理函数void*working(void*arg){structSockInfo*info=(structSockInfo*)arg;charbuf[BUFFER_SIZE];// 打印客户端连接信息charclient_ip[INET_ADDRSTRLEN];inet_ntop(AF_INET,&info->addr.sin_addr,client_ip,INET_ADDRSTRLEN);printf("[线程 %lu] 客户端连接: IP=%s, 端口=%d, fd=%d\n",pthread_self(),client_ip,ntohs(info->addr.sin_port),info->fd);// 通信循环while(1){memset(buf,0,sizeof(buf));// 接收数据intlen=read(info->fd,buf,sizeof(buf)-1);if(len==0){// 客户端断开连接printf("[线程 %lu] 客户端 %s:%d 断开连接\n",pthread_self(),client_ip,ntohs(info->addr.sin_port));break;}elseif(len<0){perror("read error");break;}// 打印接收到的数据printf("[线程 %lu] 收到数据: %s",pthread_self(),buf);// 回显数据给客户端write(info->fd,buf,len);}// 关闭连接并重置状态close(info->fd);info->fd=-1;// 标记为可用returnNULL;}关键技术点:
(struct SockInfo*)arg将 void* 转换为结构体指针read()会阻塞直到有数据到达intmain(){// 初始化客户端数组init_clients();// 1. 创建监听套接字intlfd=socket(AF_INET,SOCK_STREAM,0);if(lfd==-1){perror("socket error"