You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ Socket实现并发通信时服务端回传数据客户端接收异常问题求助

Socket通信问题排查及修复方案

第一种方案(原连接回传)收不到数据的核心原因

  • 服务端select使用错误:select调用会修改传入的文件描述符集合,每次循环调用select前必须重新将监听socket、所有已连接的客户端socket添加到读集合中。你当前代码仅在accept新连接时执行FD_SET,后续循环的select不会监听任何socket,自然无法收到客户端请求、也不会回传数据。
  • 缺少系统调用返回值判断:服务端的recv、send均未处理返回值,若recv返回0(对端断开)或负值(网络错误)时,后续的处理、发送逻辑都是无效操作;send单次调用可能无法发送全部数据,你未做循环发送处理,会导致客户端收不全数据。
  • 通信协议未对齐:客户端预期收到的第一部分内容是总数据长度的字符串,但你服务端返回的resultbuf如果没有按照约定在开头拼接总长度字符串,客户端atoi解析出的total_size为乱码,永远无法满足total_size == all_bytes_read的退出条件,会一直卡在接收逻辑中。
  • 客户端接收逻辑缺陷:recv返回<=0时未做错误判断,直接跳出内层循环后若数据未收全,会进入外层死循环反复调用recv,如果连接已断开recv会持续返回0,程序完全卡住。同时第一次recv可能只收到部分长度字段,atoi解析结果必然错误。

第二种方案(新建连接回传)B异常退出的核心原因

  • 原有线程无限阻塞:第一种方案中启动的4个线程仍在等待原socket的返回数据,无任何唤醒逻辑,会一直卡住;同时你新启动的B侧监听服务如果逻辑不完善,会进一步引发资源竞争。
  • 内存越界风险:100MB的固定大小resultbuf如果小于实际接收的数据长度,memcpy会直接越界,触发段错误导致程序崩溃。
  • 线程安全问题:多个A服务端同时向B新建连接发送数据,如果B侧的接收逻辑没有做线程同步,多个线程同时操作共享资源会引发内存 corruption,直接导致程序异常退出。

修复建议(优先修复第一种方案,满足原连接回传需求)

  1. 规范通信协议:放弃用字符串解析总长度的方式,固定报文前4字节为网络字节序的总数据长度,后续跟随实际业务数据,避免长度解析错误。
  2. 修复服务端select逻辑:每次进入while循环后,先清空读集合,再把监听socket和所有已连接的客户端socket重新添加到读集合中,再调用select。
  3. 补齐所有系统调用的返回值处理:
    • recv返回<=0时,直接关闭对应socket,从读集合中移除,跳过后续处理。
    • send要做循环发送,直到所有数据全部发送完成,或者出现错误。
    • 所有socket相关接口调用后打印错误码(Linux下取errno,Windows下取WSAGetLastError),方便快速定位问题。
  4. 修复客户端接收逻辑:
    • 先收满4字节的长度字段,转为主机字节序得到total_size后再接收后续业务数据。
    • 每次recv根据剩余未收长度调整接收缓冲区大小,避免多收数据。
    • recv返回<=0时如果还没收满total_size,直接报错退出,不要死循环。
    • 评估业务数据最大长度,resultbuf要么按需动态扩容,要么设置足够的预留空间,避免越界。
  5. 调试辅助:用tcpdump/Wireshark抓对应端口的数据包,确认服务端是否已经将响应数据发出,快速区分是网络问题还是代码逻辑问题。

内容的提问来源于stack exchange,提问作者mining

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 08:06:01