使用TCP作为网络协议,在通过网络发送消息之前,我为每条消息的大小(以及可能的校验和?)添加前缀。我想知道,计算和传输消息的校验和是否有意义,以确保消息将被传送(如果和何时传送)不变,例如,因为一些网络错误。目前,我在发送消息之前发送消息的4字节大小+ 2字节校验和(CRC-16)。另一个端点正确识别预期的消息长度,读取它并验证校验和。
我知道TCP有内部数据包验证机制,我强烈感觉我在应用程序级别的消息验证是多余的,但在做出决定之前我不确定并需要你的建议。
我正在开发客户端 - 服务器应用程序,每天有数万个与服务器的潜在连接。即使任何消息中的单个损坏字节也可能导致交换不正确消息的整个链,这是不可接受的(好吧,几乎所有客户端 - 服务器应用程序都有相同的要求,不是它们)。所以我想确定 - 我能安全地信任TCP的内部可靠性,还是提供自己的校验和验证机制更好。我说的是小的,两个字节的校验和(CRC-16),我不是在谈论数字签名消息等等(并且系统是使用套接字在.Net(C#)中开发的,如果这有任何区别的话)
答案 0 :(得分:2)
根据this paper“校验和将无法检测大约1600万到100亿个数据包中的错误”。假设数据包大小为1024字节,则每16 GB到10 TB的网络流量就会发生一次未检测到的错误。
许多协议(如HTTP,FTP,SMTP)以及可能更多的协议都依赖于底层的校验和。鉴于上述数字,我认为这种做法可疑。
旁注:硬盘驱动器也是如此。典型的台式机驱动器在10 TB读取时具有1位的错误检测能力。读取您的2 TB磁盘5次,平均而言,您将遭受一次腐败事件。
回答你的问题:如果你的容忍非常罕见,虚假的失败是中等到高,请不要打扰校验和。如果您无法容忍任何损坏,请在协议中添加校验和。
答案 1 :(得分: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的原因。
答案 2 :(得分:0)
TCP不保证100%您的数据将按照发送方式进行传输和接收。
您的 3_ABC (CRC 42 )消息偶然会被意外转换为 10_FU @0Ээ^ +Ъr CRC。但是,仍然应依赖它。
由于TCP已经发现,只需发送每个数据包的校验和并将其与另一方的内容进行比较,您不必自己进行。 TCP还保证数据按发送顺序排列,因此如果你坚持使用应该足够的模式[from 4 to 8 bytes of message's length + message itself]
。
但是,在使用消息模式的情况下,您可能会改为使用UDP。有一些方法可以准确地使用UDP而不是TCP来实现最大网络潜力。其中一个是Lidgren.Network C#库,它可以以多种可靠性和顺序发送数据包。