【问题标题】:TCP Packets are sometimes combined (and delayed?)TCP 数据包有时会合并(并延迟?)
【发布时间】:2018-07-09 15:30:57
【问题描述】:

我每 500 毫秒从服务器向客户端发送数据包,反之亦然,以表明连接仍然有效。然而,有时这些数据包被延迟并且多个数据包被组合在一起。问题是这可能会导致“连接超时”,而这可能只是延迟。

在任何现代互联网连接上,10 秒的数据包发送延迟对我来说似乎都相当长。有关如何解决此问题的任何想法?

在服务器和客户端上都可以发送和接收消息,如下例所示,其中最终接收到的数据包由几个组合在一起的数据包组成。这同时发生在服务器和客户端上。

SENT ALIVE PACKET
RECEIVED ALIVE PACKET
SENT ALIVE PACKET
RECEIVED ALIVE PACKET
SENT ALIVE PACKET
RECEIVED ALIVE PACKET
SENT ALIVE PACKET
RECEIVED ALIVE PACKET
SENT ALIVE PACKET
RECEIVED ALIVE PACKET
SENT ALIVE PACKET
SENT ALIVE PACKET
SENT ALIVE PACKET
RECEIVED ALIVE PACKET
RECEIVED ALIVE PACKET
SENT ALIVE PACKET
RECEIVED ALIVE PACKET
SENT ALIVE PACKET
RECEIVED ALIVE PACKET
SENT ALIVE PACKET
RECEIVED ALIVE PACKET
SENT ALIVE PACKET
SENT ALIVE PACKET
SENT ALIVE PACKET
SENT ALIVE PACKET
SENT ALIVE PACKET
SENT ALIVE PACKET
SENT ALIVE PACKET
SENT ALIVE PACKET
RECEIVED ALIVE PACKET RECEIVED ALIVE PACKET RECEIVED ALIVE
PACKET RECEIVED ALIVE PACKET RECEIVED ALIVE PACKET RECEIVED ALIVE
PACKET RECEIVED ALIVE PACKET RECEIVED ALIVE PACKET RECEIVED ALIVE
PACKET RECEIVED ALIVE PACKET ****RECEIVED TIMEOUT PACKET****

Connection Timeout.


编辑

这在我的另一台运行相同代码的 PC 上从未发生过。

编辑 2

数据包的合并没有问题,但是数据包应该直接发送而不是延迟。

【问题讨论】:

  • 你在使用 KEEPALIVE 吗?你在设置 TCP_NODELAY 吗?请参阅 setsockopt()。
  • send/receive 级别的 TCP/IP 是流而不是数据包协议。所以你在读取它时会得到一个连续的字节流。在较低层,它可以合并/拆分,但感觉就像你会阅读你发送的部分/多个“消息”。如果您有数据块,则可以简化消息,您需要实现消息格式;长度前缀是最简单的前缀之一。
  • @Z0q 由于 TCP/IP 对您隐藏了所有数据包详细信息,因此您无法接收“数据包”。当您调用receive 时,无论缓冲区中有多少,它都会传递给您。这可能会导致发送的消息根据传输层进行拆分或合并。
  • 我还有一个问题:定期检查 TCP 连接是否仍然存在真的有意义吗?这种机制已经包含在 TCP 本身中。

标签: c++ c sockets networking tcp


【解决方案1】:

在我的套接字中添加KEEPALIVE 选项似乎已经解决了这个问题。

感谢@cdarke。

【讨论】:

  • 我不知道怎么做。在两个小时过去之前,它的效果完全为零。您一定更改了其他内容。
  • @EJP:2 小时通常是默认值,但某些系统(如 Linux)通过setsockopt() 支持TCP_KEEPIDLETCP_KEEPINTVLTCP_KEEPCNT 套接字选项以允许每个套接字自定义SO_KEEPALIVE 使用的间隔。 Windows 没有这些选项,但它确实有 SIO_KEEPALIVE_VALS 通过WSAIoctl() 代替。
  • @RemyLebeau 确实,但是 TCP 保持连接机制中仍然没有任何东西可以解决这些延迟。我无法想象为什么它甚至被建议。他肯定禁用了 Nagle 算法,或者修复了硬件中的某些问题。
  • 我不确定我的应用程序出了什么问题。有时错误会再次出现,有时添加 printf() 可以解决问题,删除它会使问题再次出现。有时某些数据包将不会被接收(大约 100 个数据包中的 1 个)。我在想这可能是内存泄漏或未初始化的变量?
猜你喜欢
  • 1970-01-01
  • 2021-01-28
  • 2017-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-06
相关资源
最近更新 更多