通过Socket发送超过1024字节数据出现传输错误的原因咨询
问题根因
该问题和1500字节的MTU限制没有关联,和官方文档标注的1048576字节发送缓冲区上限也不冲突。核心错误是你没有处理send()、recv()的返回值:TCP是字节流协议,这两个系统调用不会保证一次性发送/接收你指定的全部长度数据,返回值才代表本次调用实际成功传输的字节数。
当你设置单次发送长度为1024时,数据大概率能一次性写入内核发送缓冲区、或被对端一次性接收完成,所以不会触发问题;当单次长度超过1024时,单次send()可能没有写完所有数据、或单次recv()没有收完所有数据,你直接忽略返回值向下执行,就会出现数据错位,最先受影响的就是作为文件传输元数据的chunk和rest变量,这两个值读错之后后续的文件读写逻辑会完全混乱。
至于官方标注的1M发送缓冲区,它指的是内核暂存应用层待发送数据的最大容量,和单次send()能发送的长度没有直接关系:就算缓冲区总容量有1M,要是当前缓冲区剩余空间不足你传入的发送长度,send()只会返回实际写入缓冲区的字节数,剩余未发送的数据需要你主动调用多次send()补发。
修复方案
你需要封装两个可靠传输的工具函数,保证指定长度的数据被完整传输后再返回:
可靠发送函数
ssize_t send_all(int fd, const void* buf, size_t len) { size_t total_sent = 0; const char* ptr = static_cast<const char*>(buf); while (total_sent < len) { ssize_t n = send(fd, ptr + total_sent, len - total_sent, 0); if (n <= 0) return n; // 连接关闭或出现错误 total_sent += n; } return total_sent; }
可靠接收函数
ssize_t recv_all(int fd, void* buf, size_t len) { size_t total_recv = 0; char* ptr = static_cast<char*>(buf); while (total_recv < len) { ssize_t n = recv(fd, ptr + total_recv, len - total_recv, 0); if (n <= 0) return n; // 连接关闭或出现错误 total_recv += n; } return total_recv; }
将你代码中所有的send()、recv()调用替换为上述封装函数即可解决问题。另外你当前代码中perror("Error: ")的调用位置不合理,只有在系统调用返回错误时调用perror才有意义,正常执行时这里会输出无意义的错误提示,建议补充错误判断逻辑后再保留。
内容的提问来源于stack exchange,提问作者isudfv
相关产品推荐
相关产品推荐

