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

TCP连接双向同时发送时出现丢包问题技术求助

嘿,我之前也碰到过类似的TCP双向并发收发时的丢包问题,结合你描述的场景——两端循环发送带序列号的128字节消息、无参GCC编译,咱们一步步拆解可能的原因和排查方向:

核心原因排查方向

1. 收发缓冲区溢出

TCP内核默认的收发缓冲区大小是有限的(不同系统默认值不同,比如Linux可能是几十KB)。当两端同时高速发送128字节消息时,如果某一端的接收缓冲区被占满,内核会直接丢弃后续到达的数据包(或者触发滑动窗口收缩,极端情况导致丢包)。

你可以试试用setsockopt手动调大缓冲区:

int buf_size = 65536; // 64KB
setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &buf_size, sizeof(buf_size));
setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size));

调整后再测试,看丢包是否缓解。

2. 未处理TCP粘包/拆包导致的逻辑误判

TCP是字节流协议,没有天然的消息边界——你的128字节消息可能被内核拆成多个TCP段发送,或者多个消息被合并成一个段发送。如果你的接收逻辑没有正确处理粘包,比如每次只调用一次recv就认为拿到了完整的128字节消息,就会出现消息不完整、序列号混乱,最终被你误判为“丢包”。

举个正确的接收逻辑示例:

char buf[128];
int total_recv = 0;
while (total_recv < 128) {
    int ret = recv(sockfd, buf + total_recv, 128 - total_recv, 0);
    if (ret <= 0) {
        // 连接出错或关闭,处理异常
        break;
    }
    total_recv += ret;
}
// 现在buf里是完整的128字节消息

3. 阻塞调用导致的收发阻塞

如果你的代码用的是阻塞式的send/recv,在双向并发收发时可能出现“互相等待”的死锁场景:比如服务端在调用recv等待客户端消息,而客户端也在调用recv等待服务端消息,此时某一端的发送缓冲区满了之后,后续的send会被阻塞,你会误以为是消息丢失了。

另外,一定要检查send的返回值——send可能只发送了部分字节(比如返回值小于128),这时候你需要循环发送剩余的字节,否则消息会不完整:

char msg[128];
// 填充msg,首字节为序列号
int total_sent = 0;
while (total_sent < 128) {
    int ret = send(sockfd, msg + total_sent, 128 - total_sent, 0);
    if (ret <= 0) {
        // 连接出错,处理异常
        break;
    }
    total_sent += ret;
}
针对你的代码的额外检查点

你给出的服务端代码只包含了头文件开头,补充几个通用的排查点:

  • 确认是否启用了TCP_NODELAY:如果开启了Nagle算法,小数据包会被合并发送,可能导致看似丢包的延迟,但不是真的丢包。你可以用setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt))关闭它试试。
  • 检查连接状态:在循环收发前,确认accept返回的连接套接字是有效的,没有被意外关闭。
  • 启用SO_KEEPALIVE:开启TCP保活可以及时检测到连接的异常(比如对方崩溃但没发FIN包),避免在无效连接上发送数据。
调试技巧
  • 抓包分析:用tcpdump或Wireshark抓两端的网络包,看数据包到底有没有被发送到网络层。如果抓包能看到所有带序列号的消息,那问题一定在接收端的逻辑;如果抓包看不到某些消息,那大概率是发送端缓冲区溢出或发送逻辑有问题。
  • 加详细日志:在每次send和recv前后打印日志,记录序列号、发送/接收的字节数、时间戳,比如:
    printf("Sent seq: %d, bytes: %d\n", msg[0], total_sent);
    printf("Received seq: %d, bytes: %d\n", buf[0], total_recv);
    
    这样能精准定位到哪一个序列号的消息丢失,以及丢失发生在发送还是接收环节。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:12:28