LINUX ---网络编程(三)
1.单客户端服务器
工作流程:socket 创建→bind 绑定→listen 监听→accept 建立单个连接→循环读写通信;
特点:一次只能处理一个客户端连接,处理完才能接受新连接;
局限性:无法同时服务多个客户端,仅适用于简单测试场景;
2.单循环多客户端服务器
工作流程:在主循环中重复执行 accept 接受连接→与客户端通信→关闭连接的过程;
特点:能处理多个客户端,但需串行处理(必须等上一个客户端断开才能处理下一个);
局限性:效率低,不支持真正的并发,适合客户端交互简单且连接数极少的场景;
3.多进程多客户端服务器
工作流程:主进程负责 accept 接受连接,通过 fork 创建子进程专门处理每个客户端的通信。
特点:
支持真正的并发处理,多个客户端可同时交互;
父进程持续接受新连接,子进程独立处理对应客户端;
需要处理僵尸进程问题(通过信号机制回收);
局限性:进程创建和切换开销较大,不适合高并发场景;
核心差异:并发能力的实现方式不同,从完全不支持并发(单客户端)→串行处理(单循环)→并行处理(多进程),逐步提升了服务器的服务能力,但也带来了更复杂的实现和更多的系统资源消耗。
实际开发中,还会根据需求选择多线程模型(线程开销小于进程)或 IO 多路复用模型(如 epoll,单进程高效处理多连接)等更优方案。
1. 地址重用(SO_REUSEADDR)
作用:解决服务器重启时因端口处于 TIME_WAIT 状态导致的 "地址已被使用" 错误,允许端口快速重新绑定。
实现方式:通过setsockopt函数设置,通常在socket()创建后、bind()之前调用:
int on = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int));
参数意义:
SOL_SOCKET:在 socket 层设置选项;
SO_REUSEADDR:开启地址重用功能的选项名;
&on:传入非 0 值表示启用该功能;
2. 多线程多客户端服务器模型
核心思想:主进程负责接受客户端连接,为每个连接创建独立线程处理通信,实现并发服务。
工作流程:
主流程:socket()创建监听套接字 → 设置地址重用 → bind()绑定 → listen()监听 → 循环accept()接受连接。
连接处理:每接受一个连接,通过pthread_create()创建线程,由线程执行do_client函数处理具体通信。
线程函数:循环read()接收数据 → 处理(如sprintf拼接响应)→ write()发送响应,直到客户端断开。
关键细节:
使用pthread_detach()设置线程分离属性,自动回收线程资源,避免僵尸线程。
连接描述符connfd需动态分配(如malloc),避免多线程共享同一地址导致的冲突。
线程结束前需释放资源(如free动态分配的内存)并关闭连接。
优势:
线程创建 / 销毁开销远小于进程,资源占用更低。
适合处理 IO密集型任务(如网络通信),并发效率高于多进程模型。
特性 | 多进程模型 | 多线程模型 |
资源开销 | 大(独立内存空间) | 小(共享进程资源 |
上下文切换 | 慢 | 快 |
通信复杂度 | 高(需 IPC 机制) | 低(可直接共享内存) |
稳定性 | 高(进程隔离) | 低(线程崩溃影响整体) |
适用场景 | 计算密集型任务 | 网络通信等IO 密集型任务 |