深入解析:Linux 软件编程(十二)网络编程:TCP 并发服务器构建与 IO 多路复用
在网络编程中,服务器需要应对多个客户端的连接与请求,单循环服务器因同一时刻仅能处理一个客户端任务,无法满足高并发场景。而 TCP 并发服务器可实现多客户端同时处理 。
一、TCP 并发服务器
(一)单循环与并发服务器区别
- 单循环服务器:同一时刻仅能处理一个客户端任务,处理完当前客户端才能响应下一个,效率低。
- 并发服务器:可同时处理多个客户端任务,提升服务端资源利用率与响应能力。
(二)TCP 连接特性
TCP 基于 “三次握手” 建立 一对一连接 ,可靠传输数据,但需高效并发模型支撑多客户端交互。
二、TCP 服务端并发模型
(一)多进程模型
- 原理:服务端通过
fork()创建子进程,父进程负责监听新连接,子进程处理客户端交互。 - 特点:
- 资源开销大:进程有独立地址空间,创建、切换成本高。
- 安全性高:进程间资源隔离,一个进程异常一般不影响其他进程。
- 代码示例:
#include
#include /* See NOTES */
#include
#include
#include
#include /* superset of previous */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SER_PORT 50000
#define SER_IP "192.168.0.149"
struct sockaddr_in seraddr;
void hander(int handnum)
{
wait(NULL);
}
int init_tcp_recv()
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd 0)
{
}
else if(pid == 0)
{
char buff[1024] = {0};
while(1)
{
memset(buff, 0, sizeof(buff));
int ret = recv(connfd, buff, sizeof(buff), 0);
if(ret ok");
int cnt = send(connfd, buff, strlen(buff), 0);
if(cnt < 0)
{
perror("send error");
close(connfd);
break;
}
}
}
}
close(sockfd);
return 0;
}
(二)多线程模型
- 原理:借助
pthread_create()创建线程,主线程负责accept新连接,子线程处理客户端数据收发。 - 特点:
- 资源开销小:线程共享进程地址空间,创建、切换成本低于进程,相同资源环境下并发量更高。
- 需注意同步:线程共享资源,如需客户端地址信息等,需用锁机制(如互斥锁)避免竞争,否则易引发数据混乱,或者创建结构体将客户端信息和通信套接字放在里面,然后线程传参时第四个参数传入结构体的地址,然后进行访问内容。
- 伪代码示例:
#include
#include /* See NOTES */
#include
#include
#include
#include /* superset of previous */
#include
#include
#include
#include
#include
#include
#include
#include
#define SER_PORT 50000
#define SER_IP "192.168.0.149"
struct sockaddr_in seraddr;
int init_tcp_recv()
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd ok");
int cnt = send(connfd, buff, strlen(buff), 0);
if(cnt < 0)
{
perror("send error");
close(connfd);
break;
}
}
return NULL;
}
int main(int argc, char const *argv[])
{
int sockfd = init_tcp_recv();
if(sockfd < 0)
{
return -1;
}
pthread_t tid;
while(1)
{
int connfd = accept(sockfd, NULL, NULL);
if(connfd < 0)
{
perror("accept error");
return -1;
}
pthread_create(&tid, NULL, recv_senf, &connfd);
pthread_detach(tid);
}
close(sockfd);
return 0;
}
(三)线程池模型
- 背景:多线程 / 多进程模型中,频繁创建、销毁线程 / 进程会产生大量时间消耗。线程池基于 生产者 - 消费者模型 与 任务队列 ,预先创建一定数量线程,复用线程处理任务,减少资源开销。
- 原理:
- 生产者(主线程):负责
accept客户端连接,将任务(如处理客户端请求)放入任务队列。 - 消费者(线程池中的次线程):从任务队列取出任务并执行,执行完可继续获取新任务,无需频繁创建销毁。
- 生产者(主线程):负责
- 模型示意图:
主线程作为生产者生产任务(如客户端连接处理任务),放入任务队列;多个次线程作为消费者,从队列取任务执行,实现任务高效复用与并发处理。

(四)IO 多路复用模型
- 核心思想:让一个进程 / 线程 复用多个文件描述符(fd)的读写操作 ,不创建新进程 / 线程,通过一个进程监测、处理多个文件(如 socket 连接)的读写事件。
- 应用场景:需同时监听多个
fd(如stdin、connfd等),避免阻塞 IO 导致程序 “卡主”,典型函数有select、poll、epoll。
(1)select 函数
- 函数与操作步骤:
- 创建文件描述符集合:用
fd_set类型,通过FD_ZERO清空集合,FD_SET添加关注的fd。 - 传递集合给内核监测:调用
select函数,内核监测集合中fd的事件(读、写、异常等),监测期间进程阻塞。 - 处理事件:内核监测到事件后,
select解除阻塞,通过FD_ISSET判断具体fd事件,执行对应读写操作。
- 创建文件描述符集合:用
- 关键函数与
select原型: void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
功能:传递文件描述符结合表给内核并等待获取事件结果
参数:
nfds : 关注的最大文件描述符+1
readfds:读事件的文件描述符集合
writefds:写事件的文件描述符集合
exceptfds:其他事件的文件描述符集合
timeout:设置select监测时的超时时间
NULL : 不设置超时时间(select一直阻塞等待)返回值:
成功:返回内核监测的到达事件的个数
失败:-1
0 : 超时时间到达,但没有事件发生,则返回- 伪代码示例(结合 TCP 服务端):
#include
#include
#include
#include
#include
#include
#include /* See NOTES */
#include
#include /* superset of previous */
#include
#include
#include
#include
#define SER_PORT 50000
#define SER_IP "192.168.0.149"
struct sockaddr_in seraddr;
int init_tcp_recv()
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd connfd ? maxfd : connfd;
}
for(int i = sockfd + 1;i ok");
cnt = send(i, buff, strlen(buff), 0);
if(cnt < 0)
{
perror("send error");
FD_CLR(i, &rdfds);
close(i);
continue;
}
}
}
}
close(sockfd);
return 0;
}
- 特点:
- 需维护
fd集合,每次select后需重新添加fd(因内核会修改集合)。 fd数量受限(受系统默认限制,如 1024 ),高并发场景可能不够用。
- 需维护
(2)poll/epoll
- poll:与
select类似,通过struct pollfd数组传递监测的fd及事件,解决select中fd数量受限问题,但本质仍需遍历fd判断事件,高并发下效率一般。 - epoll:Linux 下高效的 IO 多路复用机制,通过 红黑树 维护监测的
fd,回调机制 通知事件,无需遍历所有fd,高并发场景(如大量客户端连接)效率远高于select/poll。
三、总结
TCP 并发服务器构建有多种模式:
- 多进程模型资源开销大但安全;
- 多线程模型轻量但需注意同步;
- 线程池模型优化线程资源管理,适配高频任务场景;
- IO 多路复用(
select/poll/epoll)让单进程实现多fd监测,高效处理并发连接。
浙公网安备 33010602011771号