【问题标题】:Sending variable sized packets over the network using TCP/IP使用 TCP/IP 通过网络发送可变大小的数据包
【发布时间】:2024-01-18 17:17:01
【问题描述】:

我想通过内部网络在 2 个 linux 操作系统之间发送可变大小的数据包。数据包是可变大小的,它的长度和 CRC 在与数据包一起发送的标头中指示。有点像-

struct hdr {
    uint32 crc;
    uint32 dataSize;
    void *data;
};

我在应用层使用 CRC 来克服固有的limitation of TCP checksums

我的问题是,dataSize 字段本身有可能已损坏,在这种情况下,我不知道下一个数据包从哪里开始?因为在接收器上,当我读取套接字缓冲区时,我读取了n 这样的数据包并排在一起。所以dataSize 是我正确获取下一个数据包的唯一方法。

我的一些想法是-

  1. 如果发生 CRC 不匹配,请重新启动连接。
  2. X这样的数据包聚合成一个固定大小的大数据包,如果检测到任何CRC错误,则丢弃该大数据包。大数据包是为了确保我们丢失

对于这些可变大小的数据包还有其他想法吗?

【问题讨论】:

    标签: c linux sockets networking tcp


    【解决方案1】:

    由于 TCP 是基于流的,因此数据长度是提取一条完整消息以供应用程序处理的常用方法。如果您认为由于某种原因长度字节本身是错误的,那么除了丢弃数据包“刷新”连接并期望发送方和接收方重新同步之外,我们无能为力。但最好是断开线路,除非应用层有协议可以重新同步连接。

    除了长度字节之外的另一种方法是使用标记。消息开始和消息结束。应用程序遇到消息开始时应该开始收集数据,直到收到消息结束字节,然后进一步处理消息。这要求消息适当地转义标记。

    【讨论】:

      【解决方案2】:

      我认为当主要风险在其他地方时,您正在处理二阶错误的可能性。

      当我们使用串行线路传输时,错误是频繁(每几个 kBytes 出现一两个)。我们使用带有 CRC 和大约 100 字节的数据包大小的好旧 Kermit,这就足够了:我多次遇到传输失败,因为线路中断,但从来没有正确传输错误文件。

      在当前的网络中,除非你的线路很差,否则硬件水平并没有那么差,而且无论如何第 2 级数据链路层已经有一个校验和来控制每个数据包在 2 个节点之间没有被修改。 HDLC 通常用于该级别,它通常使用 CRC16 或 CRC32 校验和,这是一个非常正确的校验和。

      因此,作为 TCP 级别的校验和并不是为了检测字节流中的随机错误,而只是作为意外错误的最后一道防线,例如,如果路由器因电气故障而发疯震惊并发送完整的垃圾。我没有任何统计数据,但我很确定达到 TCP 级别的错误数量已经非常非常低。换一种说法,不要担心:除非您正在处理高度敏感的数据 - 在这种情况下,我希望有两个不同的通道,前者用于数据,后者用于全局校验和 - TCP/IP 就足够了。

      话虽如此,在应用程序级别添加控件作为终极防御是完全可以接受的。它只会处理可能在数据链路和 TCP 级别未检测到的错误,或者更可能是对等应用程序中的错误(谁编写了它,它是如何测试的?)。因此出现错误的概率足够低,可以使用非常粗略的恢复过程:

      • 关闭连接
      • 打开一个新的
      • 在正确交换最后一个数据包后重新启动(如果有意义的话),或者在可以的情况下继续发送新数据包

      但是在网络中任何地方发生物理断开或断电的风险要高得多,而不是说应用程序级实现中的缺陷......

      并且不要忘记完全指定字节顺序以及crc和datasize的大小......

      【讨论】:

        最近更新 更多