【问题标题】:I need to receive two packets separately - linux combines them as one and sends to the application我需要分别接收两个数据包 - linux将它们合并为一个并发送给应用程序
【发布时间】:2020-06-21 17:00:53
【问题描述】:

我的设备已连接到 TCP 服务器,该服务器会定期发送心跳。有时,这个心跳数据包与其他一些数据包一起到达,并且在我正在通过套接字读取的程序中,这两个数据包被组合并作为单个数据包读取,这会导致应用程序逻辑出现应用程序问题。我仍然可以添加一些解决方法,但是有没有办法告诉内核将这两个数据包作为单独的数据包而不是作为一个单独的数据包发送?

服务器上的逻辑 - 接受传入连接,当设备连接时,创建一个单独的线程与设备通信,设置 TCP_NODELAY,我在从套接字读取数据之前使用轮询。在任何给定时间点大约有 100 个线程。

【问题讨论】:

  • 当设备发生某些事件时,另一个到达的数据包也是有效的数据包。
  • 如果您有两个独立的协议(心跳和数据),那么它们可能位于不同的套接字上。
  • 服务器有责任以这样一种方式划分其消息,以便客户端可以知道一条消息在哪里结束,下一条消息从哪里开始,并且不重叠它们。在 TCP 中,有几种方法可以对消息进行成帧,但我们不知道该服务器实际使用的是什么协议,因此我们无法告诉您实际使用的是哪种成帧。实际的协议是什么样的?

标签: c linux sockets tcp network-programming


【解决方案1】:

TCP 是一种流协议。您应该依赖数据包边界来检测消息边界。任何一台机器的操作系统、网卡或中间路由器都可以在任何时候组合和拆分数据包。不要期望每个write() 系统调用都会有一个对应的read()

同样,您不能依赖整个接收的数据包。您必须处理部分读取的可能性。您可以随时从read() 调用中获取部分数据包。

在应用程序级别实现消息框架是标准做法:在每条消息前面加上一个标头,该标头包括长度,可能还包括消息 ID。读取长度,然后读取那么多字节。如果您没有获得所有请求的字节,请循环并重试。

【讨论】:

  • "为每条消息添加一个包含长度的标题" - 这是一种方式。另一种方法是使用唯一的分隔符分隔不同的消息。另一种方法是使用固定长度的消息。由于我们不知道使用的是哪种服务器,因此我们无法真正说出使用的是哪种框架。
  • 感谢您的回复,我将不得不在应用程序中处理相同的问题。
猜你喜欢
  • 2011-09-26
  • 2012-01-23
  • 2020-02-21
  • 2015-10-27
  • 1970-01-01
  • 2014-05-09
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
相关资源
最近更新 更多