C Socket编程自定义read_all函数阻塞、put命令失效问题排查
问题排查结论
- 首先
read_all函数本身的读写逻辑是正确的,你观察到的阻塞现象是因为read系统调用没有收到客户端发送的对应数据,内核默认会阻塞等待直到有数据到达/对端断开连接,问题出在发送端的参数错误和返回值判断逻辑错误。 - 第一个核心错误:发送长度的
write_all调用参数与返回值判断完全不匹配
你当前发送长度的代码存在逻辑漏洞:
你要发送的是存储长度的write_all(descr, &sen , sizeof(len))) != len)sen变量,第三个参数应该传sizeof(sen)(也就是4字节,对应网络字节序的32位整数),但你判断返回值是否等于len(protobuf打包后的消息体长度,比如你当前场景的6)。这会导致只要len不等于4,就会判定发送失败,客户端提前终止逻辑、关闭连接,服务端自然收不到后续的6字节数据,卡在read调用。
正确的判断逻辑应该是:if (write_all(descr, &sen, sizeof(sen)) != sizeof(sen)) { // 发送长度失败,处理错误 } - 第二个错误:疑似函数名笔误
你写的unsigned sen = htoml(len)大概率是htonl(主机字节序转网络字节序32位)的笔误,如果实际代码里确实写的是htoml,会导致序列化的长度值错误,服务端用ntohl转换后得到错误的长度值,后续读取逻辑异常。 - 第三个隐患:类型不匹配的隐式转换
read_all的第三个参数是有符号int类型,你传入的len是无符号类型,如果后续消息体长度超过int的最大值,会溢出为负数传入read_all,导致left初始值为负,直接跳过循环返回0,引发逻辑错误。建议将read_all、write_all的长度参数统一改为size_t(无符号整数类型,专门表示长度)。 - 补充注意:你提到「读取长度的逻辑能正常返回0符合预期」是错误的,
read_all返回0说明对端已经关闭了连接,正常读取长度的场景下应该返回sizeof(rec)(也就是4字节)才符合预期,这也验证了客户端提前关闭连接的结论。
内容的提问来源于stack exchange,提问作者Isaacovsky
相关产品推荐
相关产品推荐

