【问题标题】:Understanding how to send larger data chunks over UDP reliably了解如何通过 UDP 可靠地发送更大的数据块
【发布时间】:2013-12-17 08:02:59
【问题描述】:

多年来,我在很多事情上都使用过 TCP,并且非常了解它。我现在需要使用 UDP。

短版:服务器允许少量客户端 (5-10) 连接。服务器正在运行模拟。客户应该能够更新模拟参数并查看模拟结果的(子集)。

在这种情况下,时间(参数更改时)很重要,客户端请求更改与执行之间的延迟必须尽可能短。

我已经doingalotofreading,但我仍然没有“得到它”。

有人可以确认/否认我的理解吗...

  • 数据报存储在单个数据包中
  • 我可以可靠发送的最大有效负载为 506 字节(576 MTU - 60 IP 标头 - 8 UDP 标头)
  • 发送过多可能会导致碎片化
  • 碎片不在较低级别处理,需要我重新组合数据报(不确定 - 如果它是自动处理的,我为什么要关心碎片?)
  • 我需要实现自己的 ACK/Throttling 机制

所以...如果我想从客户端向服务器发送(比如说)800 字节的数据,我需要:

  • 确定要使用的任意“协议”ID,该 ID 由客户端和服务器之间通用的 Byte(2) 表示,用于过滤不适合我的应用的消息。

客户

  • 创建一个随机消息 ID
  • 将数据一分为二,添加消息 ID 和全局序列,以便它们可以在另一端重新加入
  • 根据序列 id 在内存中的某处记录数据
  • 将它们发送到服务器
  • 如果在给定时间跨度(例如 RTT * 3)内未收到 Ack,则重新发送该数据包。

服务器

  • 在模拟循环内部,检查(非阻塞)套接字上是否有消息。
  • 如果是这样,立即发回一个包含序列 Id 的 ACK 的新数据包(实际上,为了减少 Ack 数据包丢失,我应该确认最后收到的 30 个左右的数据包)
  • 将数据包存储在内存中,直到我收到第二部分
  • 将两者结合起来处理payload

对于相反方向的消息,我需要完全相反地做同样的事情。

我不禁觉得我遗漏了一些东西,并且不太了解数据包分段的含义。有人可以澄清/指出更好的资源吗?

【问题讨论】:

  • 不会自动处理。 Socket.DontFragment 属性默认为 true。您无法返回告诉您数据包太大的 ICMP 消息。将其设置为 false 需要您解决数据包乱序并仍能正确识别它们的问题。可靠的UDP之前做过很多次,最好用a library
  • @HansPassant 感谢您的链接(以及已删除答案中的信息)。那个图书馆看起来像我需要的。如果我可以避免重新发明轮子,我很乐意这样做。
  • UDP 标头是 28 字节,而不是 68 字节。@HansPassant 它由 IP 层自动处理,包括片段排序。 UDP分片的问题不是分片排序,而是没有重传,这意味着丢失的片段==丢失的数据报。

标签: .net sockets networking udp


【解决方案1】:
  • 数据报存储在单个数据包中

不一定。

  • 我可以可靠发送的最大有效负载是 506 字节(576 MTU - 60 IP 标头 - 8 UDP 标头)

不正确。 IP 标头是 20 字节,而不是 60,所以总标头是 28 字节。剩下的就是 576-28=548,但通常是 534。

  • 发送过多可能会导致碎片化

是的。

  • 碎片不在较低级别处理,需要我重新组合数据报(不确定 - 如果它是自动处理的,我为什么要关心碎片?)

不正确。分段完全在 IP 级别处理。 UDP中分片的问题是没有针对丢失分片的ACK/重传机制,所以一个丢失的分片就意味着整个数据报都丢失了。您看到的要么是整个 UDP 数据报,要么什么都没有。

  • 我需要实现自己的 ACK/Throttling 机制

是的。 W.R. Stevens, Unix Network Programming, vol I 中给出了一个简单的 ACK/重试方案。

【讨论】:

  • 感谢您的信息,但回复:我已经阅读了 20-60 的 IP 标头是可能的...Since an IPv4 header may contain a variable number of options, this field specifies the size of the header (this also coincides with the offset to the data). The minimum value for this field is 5 (RFC 791), which is a length of 5×32 = 160 bits = 20 bytes. Being a 4-bit value, the maximum length is 15 words (15×32 bits) or 480 bits = 60 bytes.en.wikipedia.org/wiki/IPv4#Header
  • @Basic 这是为了允许 TCP 中的所有可能性。它们在 UDP 中不存在。
  • 感谢您的所有帮助。最后,我能够非常顺利地完成一些工作,您的回答为我指明了正确的方向。
【解决方案2】:

数据报存储在单个数据包中

没有。

我可以可靠发送的最大有效负载是 506 字节(576 MTU - 60 IP 标头 - 8 个 UDP 标头)

“可靠发送”在不同的层次上意味着不同的东西。

发送过多可能会导致碎片

经济实惠。

碎片不在较低级别处理,需要我 重组数据报(不确定这个 - 如果它被处理 自动,我为什么要关心碎片?)

取决于你的水平。在应用程序级别,数据报要么完整接收,要么根本不接收。

子问题:太宽泛了,但听起来您应该改用 TCP。

【讨论】:

  • 抱歉,如果这太宽泛了 - 不幸的是,我正在处理未知的未知数。你可能是对的:TCP。从根本上说,我想要的是具有较低延迟的 TCP。显然这是一个白日梦,我需要妥协。将状态从服务器传递到客户端可能是有损的,但不会产生不利影响。从客户端到服务器必须“尽快”到达。您介意扩大您的答案以解释否/经济响应吗?谢谢
  • @Basic “具有较低延迟的TCP”只能表示“没有流量控制、ACK/重传、排序、慢启动、拥塞避免……的TCP”,即所有你真正需要的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
  • 2011-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多