TCP服务器先sleep再关闭socket导致无法处理并发请求问题
TCP服务器交换sleep与socket关闭顺序后并发失效的原因分析
原程序正常并发的逻辑
你的服务器启动了5个子进程,所有子进程共享同一个监听套接字sfd。原代码中,子进程处理连接的流程是:
- 调用
accept获取新连接的connfd - 向客户端发送时间戳
- 立即调用
fclose(fp)关闭连接(fclose会间接关闭connfd) - 睡眠5秒
这种情况下,每个子进程处理完一个连接后会快速释放自己的"处理能力"——关闭连接后,子进程会回到循环开头重新调用accept,等待新的连接请求。当有多个客户端同时连接时,5个子进程可以各自处理一个连接,空闲的子进程会继续响应新请求,所以并发是正常的。
交换顺序后并发失效的核心原因
当你把sleep(5)和fclose(fp)的顺序调换后,子进程的处理流程变成:
- 获取连接并发送时间戳
- 先睡眠5秒
- 睡眠结束后才关闭连接
问题出在睡眠的5秒内,当前子进程被阻塞在sleep调用上,无法回到循环开头执行accept。因为你只有5个子进程,当同时有5个客户端连接时,所有子进程都会进入睡眠状态,没有任何子进程能处理新的连接请求。后续的客户端请求会被积压在监听队列中,直到某个子进程睡眠结束、关闭连接并回到accept调用时,才能被处理——这就导致服务器看起来完全失去了并发能力。
另外需要注意:
- 监听套接字
sfd是被所有子进程共享的,内核会在有新连接时唤醒等待在accept上的子进程,这部分逻辑没有问题。 fclose(fp)不仅会关闭文件流,还会关闭底层的connfd,释放该连接的资源;而睡眠期间connfd处于打开状态,但子进程无法处理新请求,属于资源占用但闲置的状态。
关键代码对比
原正常逻辑:
fprintf(fp, MSG_TYPE, time(NULL)); fclose(fp); // 立即关闭连接,释放处理能力 sleep(5); // 睡眠期间子进程已回到accept等待
交换后失效逻辑:
fprintf(fp, MSG_TYPE, time(NULL)); sleep(5); // 子进程被阻塞,无法处理新连接 fclose(fp); // 睡眠结束后才释放连接
内容的提问来源于stack exchange,提问作者477
相关产品推荐
相关产品推荐

