6

使用 TCP 作为网络协议,我在通过线路发送消息之前为每条消息的大小(可能还有校验和?)添加前缀。我想知道,计算和传输消息的校验和是否有意义,以确保消息将被传递(如果以及何时传递)不变,例如由于某些网络错误。目前,在发送消息本身之前,我正在发送消息的 4 字节大小 + 2 字节校验和 (CRC-16)。另一个端点正确识别预期消息长度、读取它并验证校验和。

我知道 TCP 有内部的数据包验证机制,我有一种强烈的感觉,我在应用程序级别的消息验证是多余的,但我不确定,在我做决定之前需要你的建议。

我正在开发客户端-服务器应用程序,每天有数以万计的潜在连接到服务器。甚至任何消息中的单个损坏字节都可能导致整个链的错误消息交换,这是不可接受的(嗯,几乎所有客户端-服务器应用程序都有相同的要求,不是吗)。所以我想确定一下——我可以安全地信任 TCP 的内部可靠性,还是提供我自己的校验和验证机制更好。而且我说的是小的两字节校验和(CRC-16),我不是在谈论数字签名消息等(并且该系统是在.Net(C#)中使用套接字开发的,如果这有什么不同的话) .

4

3 回答 3

2

根据这篇论文,“校验和将无法检测到大约 1600 万到 100 亿个数据包中的 1 个错误”。假设数据包大小为 1024 字节,这相当于每 16 GB 到 10 TB 的网络流量有一个未检测到的错误。

HTTP、FTP、SMTP 等许多协议以及可能更多的协议都依赖于底层的校验和。我相信,鉴于上述数字,这种做法是有问题的。

旁注:硬盘驱动器也是如此。典型的台式机驱动器在 10 TB 读取中具有 1 位的错误检测能力。读取 2 TB 磁盘 5 次,平均而言,您将遭受一次损坏事件。

回答您的问题:如果您对非常罕见的虚假故障的容忍度是中到高,请不要打扰校验和。如果您不能容忍任何损坏,请在您的协议中添加校验和。

于 2013-10-06T18:59:20.660 回答
1

就 TCP 而言,正如其他人指出的那样,它不是 100% 可靠的,并且某些消息在传输过程中可能会损坏。

为了保持消息的完整性,您必须在应用程序级别使用 CRC。

但是,如果您使用 SSL/TLS,那么您不必在应用程序级别执行 CRC,因为它已经完成了。库检查通过 SSL/TLS 交换的消息的完整性。SSL/TLS 密码套件中的几乎所有算法都执行消息身份验证。要知道哪些算法可以使用 HMAC 或没有,或者有更可靠的算法,您必须查看它的名称。算法名称由三个部分组成。例如,

  "TLS_RSA_WITH_AES_256_GCM_SHA384" has following three parts;

  TSL_RSA     => Asymmetric algorithm for key exchange during initial handshake.
  AES_256_GCM => Symmetric algorithm for message encryption.
  SHA384      => HMAC for message integrity.

因此,在上述 SSL/TLS 算法中,SHA384 用于消息身份验证,这就是您不必在应用程序中执行 CRC 的原因。

于 2018-07-06T01:36:04.497 回答
0

TCP 不保证 100% 您的数据将按照发送的方式传输和接收。

具有 CRC 42的消息3_ABC总是有可能意外地转换为具有相同 CRC 的10_FU@0Ээ^+Ъr 。但是,您仍然应该依赖它。

正如您已经发现的那样,由于 TCP 只是发送每个数据包的校验和并将其与另一端的内容进行比较,因此您不必自己做。TCP 还保证数据按照发送的顺序出现,所以如果你坚持这种模式 [from 4 to 8 bytes of message's length + message itself]就足够了。

但是,在您使用消息模式的情况下,您可能会转而使用 UDP。有一些方法可以完全使用 UDP 而不是 TCP 来实现最大网络潜力。其中之一是Lidgren.Network C# 库,它可以以多种可靠性和顺序发送数据包。

于 2013-10-05T13:44:08.683 回答