udp文件传输项目 - 是否需要进行错误检查?

时间:2013-02-19 16:24:06

标签: java file udp protocols transfer

我已经获得了使用UDP传输文件的经典任务。在不同的资源上,我已经阅读了检查数据包错误(将CRC与数据一起添加到数据包)是必要的并且UDP已经检查了损坏的数据包并丢弃它们,因此我只需要担心重新发送丢弃的数据包。

其中哪一个是正确的?我是否需要手动对到达的数据包执行完整性检查,或者已经丢弃了不正确的数据包?

顺便说一句,该项目的语言是Java。

编辑:一些来源(课程书,互联网)说校验和只覆盖标题,因此确保发送者和接收者IP是正确的等等。有些消息来源称校验和涵盖了数据段。一些消息来源称校验和可能涵盖数据段但是它是可选的并由操作系统决定。

编辑2:问我的教授,他们说IPv4中的UDP错误检查在IPv4中是可选的,在IPv6中是默认的。但我仍然不知道它是由程序员控制,还是操作系统,还是其他层......

4 个答案:

答案 0 :(得分:3)

第一个事实:

UDP具有16位校验和字段,从包头的第40位开始。这遭受(至少)2个弱点:

  • 校验和不是必需的,所有设置为0的位都定义为“无校验和”
  • 严格来说这是一个16位检查 - 总和,所以很容易受到未检测到的损坏。

这意味着UDP的内置校验和可能足够或不够可靠,具体取决于您的环境。

第二个事实:

比运输中的数据缓存更加真实的威胁是数据包丢失重新排序:USP不保证

  • 所有数据包(最终)全部到达
  • 数据包以与发送时相同的顺序到达

事实上,UDP根本没有内置机制来处理比单个数据包更大的有效载荷,因为它不是为此而构建的。

结论:

在没有附加措施的情况下在数据包之后附加数据包必然会产生与发送流不同的接收流,除了最有利的环境之外,使其成为直接文件传输的最佳协议。

如果执行想要或必须使用UDP来传输文件,则需要构建这些部分,这些部分是TCP的组成部分,而不是UDP到应用程序中。但有一种说法,这很可能会导致TCP的重新实现。

成功实施包括许多对等文件共享协议,其中防止连接中断和丢包或重新排序需要成为应用程序功能的一部分,以打败或减轻过滤器。

实施建议:

对我们有用的是一个分块窗口实现:有效负载被分成固定且方便长度的块(我们使用了1023个字节),N个这样的块的状态数组保留在发送和接收端。< / p>

在发送方:

  • 启动UDP消息,包含这样一个块,它在流中的序列号(不止一次)以及校验和或散列。
  • 状态数组将此块标记为“已发送/待处理”,并带有时间戳
  • 如果使用完整状态数组(发送窗口),则发送停止

在接收方:

  • 收到的数据包将根据其校验和进行检查,
  • 如果序列号的所有副本都一致,则删除损坏的数据包,否则将其删除
  • 确定数据包在状态数组中标记为“已接收/待定”并带有时间戳
  • 如果已收到足够的块来填充ack数据包,或者最旧的“接收/挂起”的时间戳变得太旧(某些ms到约100ms),则确认通过发送ack数据包来工作。
  • Ack数据包需要校验和,但没有排序。
  • 已发送确认的Chunks在状态数组中标记为“ack / pending”且时间戳

在发送方:

  • 接收并检查Ack数据包,丢弃损坏的数据包
  • 收到ack的Chunks在状态数组中标记为“ack / done”
  • 如果状态数组中的第一个块标记为“ack / done”,则状态数组会向上滑动,直到它的第一个块再次完成为止。
  • 这可能会释放一个或多个未发送的未发送块。
  • 对于处于“已发送/待定”状态的块,时间戳上的超时会触发此块的新发送,因为原始块可能已丢失。

在接收方:

  • 接收块i + N(N是窗口宽度)将块i标记为ack / done,向上滑动接收窗口。如果不是从接收窗口滑出的所有块都被标记为“ack / pending”,则构成不可恢复的错误。
  • 对于状态为“ack / pending”的块,时间戳上的超时会触发此块的新ack,因为原始ack消息可能已丢失。

显然需要来自发送方的特殊消息类型,如果发送窗口滑出文件的末尾,发信号接收ack而不发送块N + i,我们通过简单地发送N来实现它块不仅存在,而且没有有效载荷。

答案 1 :(得分:2)

您可以确定收到的数据包与发送的数据包相同(例如,如果您发送数据包A并接收数据包A,则可以确定它们是相同的)。对数据包的传输层CRC校验可确保这一点。但由于UDP无法保证交付,因此您需要确保已收到已发送的所有内容,并且需要确保正确订购。

换句话说,如果按顺序发送数据包A,B和C,您实际上可能只接收A和B(或没有)。您可能会将它们排除在外,C,B,A。因此,您的检查需要处理TCP提供的保证交付方面(验证排序,确保所有数据都存在,并通知服务器重新发送您所做的任何事情'无论您需要什么程度

优先选择UDP over TCP的原因是,对于某些应用程序,数据排序和数据完整性都不重要。例如,当流式传输AAC音频数据包时,各个音频帧非常小,以至于可以安全地丢弃或播放少量音频帧,而不会在很大程度上破坏收听体验。如果99.9%的数据包被正确接收和订购,你可以正常播放流,没有人会注意到。这适用于某些蜂窝/移动应用程序,您甚至不必担心重新发送丢失的帧(请注意,Shoutcast和其他一些服务器在某些情况下使用TCP进行流式传输[以促进带内元数据],但它们不会不得不。)

如果您需要确保所有数据都在那里并且订购正确,那么您应该使用TCP,它将负责验证数据是否全部存在,正确排序,并在必要时重新发送。

答案 2 :(得分:2)

UDP协议使用相同的策略来检查TCP协议使用的错误数据包 - 数据包标头中的16位校验和。

UDP数据包结构是众所周知的(以及TCP),因此如果不加密,数据包很容易被篡改,添加另一个校验和(例如CRC-32)也会使其更加健壮。如果目的是加密数据(手动或通过SSL通道),我不打算添加另一个校验和。

请注意,数据包可以发送两次。请务必相应处理。

您可以检查维基百科上的两个数据包结构,两者都有校验和:

您可以更详细地检查TCP数据包结构,以获取有关如何处理丢弃数据包的提示。 TCP协议为此目的使用“序列号”和“确认号”。

我希望这会有所帮助,祝你好运。

答案 3 :(得分:1)

UDP将丢弃不符合内部每包校验和的数据包; CRC检查有助于在应用层确定一旦有效载荷看起来是否完整,接收的内容是否实际完成(没有丢弃的数据包)并匹配发送的内容(没有中间人或其他攻击)