我想通过内部网络在2个Linux操作系统之间发送可变大小的数据包。该分组是可变大小的,并且其长度和CRC在报头中指示,该报头也与分组一起发送。大致像 -
struct hdr {
uint32 crc;
uint32 dataSize;
void *data;
};
我在应用层使用CRC来克服固有的limitation of TCP checksums
我遇到的问题是,dataSize
字段本身有可能被破坏,在这种情况下,我不知道下一个数据包的起始位置是什么?在reciver中,当我读取套接字缓冲区时,我读取n
这样的数据包彼此相邻。所以dataSize
是我能够正确访问下一个数据包的唯一方法。
我的一些想法是 -
X
个此类数据包聚合成一个固定大小的数据包,如果检测到任何CRC错误,则丢弃该数据包。大数据包是为了确保在出现错误时丢失< = sizeof of one packet 这些可变大小的数据包的其他想法?
答案 0 :(得分:1)
由于TCP是基于流的,因此数据长度是提取一个完整消息以便在应用程序处理的常用方法。如果您认为长度字节本身由于某种原因是错误的,除了丢弃数据包之外我们无能为力,“刷新”连接并期望发送方和接收方重新同步。但最好是断开线路,除非在应用层有一个协议来重新同步连接。
除长度字节之外的另一种方法是使用标记。消息开始和消息结束。遇到Message-Start-Message时的应用程序应该开始收集数据,直到收到End-of-Message字节,然后进一步处理该消息。这要求消息适当地转义标记。
答案 1 :(得分:1)
我认为你正处理二阶错误的可能性,当主要风险在其他地方时。
当我们使用串行线传输时,错误频繁(每隔几个字节一个或两个)。我们使用了一个好的旧Kermit,CRC和一个大约100字节的数据包大小就足够了:我遇到很多次传输失败,因为线路已经关闭,但从来没有正确传输带有坏文件。
对于当前网络,除非你的线路非常差,否则硬件级别并不差,无论如何,2级数据链路层已经有一个校验和来控制每个数据包在2个节点之间没有被修改。 HDLC通常在该级别使用,它通常使用CRC16或CRC32校验和,这是一个非常正确的校验和。
因此校验和作为TCP级别并不意味着检测字节流中的随机错误,而只是作为意外错误的最后防线,例如,如果路由器由于电气而生气震惊并发送完整的垃圾。我没有任何统计数据,但我很确定达到TCP级别的错误数量已经非常低。换句话说,不要担心:除非您正在处理高度敏感的数据 - 在这种情况下,我会优先使用两个不同的通道,前者用于数据,后者用于全局校验和 - TCP / IP就足够了。
话虽如此,在应用程序级别添加一个控件作为ultime防御是完全可以接受的。它只会处理在数据链路和TCP级别未检测到的错误,或者更可能是对等应用程序中的错误(谁编写它以及如何测试?)。因此,获得错误的可能性很低,足以使用非常粗略的恢复过程:
但是,在网络中的任何地方实现物理断开或断电的风险要高得多,而不是在应用程序级实现中存在缺陷......
并且不要忘记完全指定字节顺序以及crc和datasize的大小...