使用TCP时,是否需要使用校验和来保护我的消息?

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

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

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

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

许多协议,如HTTP,FTP,SMTP以及可能更多的协议都依赖于底层的校验和。 鉴于上述数字,我认为这种做法值得怀疑

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

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

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

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

但是,如果您使用SSL / TLS,那么您不必在应用程序级别执行CRC,因为它已经完成。 通过SSL / TLS交换的消息由库检查完整性。 SSL / TLS密码套件中的几乎所有算法都执行消息validation。 要知道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用于消息validation,这就是您不必在应用程序中执行CRC的原因。

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

使用相同的CRC,您的带有CRC 42的消息3_ABC偶然会被意外转换为10_FU @0Ээ^ +Ъr 。 但是,你仍然应该依赖它。

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

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