了解如何通过UDP可靠地发送更大的数据块

Bas*_*sic 2 .net sockets networking udp

多年来,我已经将TCP用于很多事情并且很好地理解它.我现在要求使用UDP.

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

在这种情况下,定时(当参数改变时)很重要,并且请求改变的客户端和正在实现改变的客户端之间的延迟必须尽可能低.

我一直在 一个 大量 阅读,我仍然没有"得到它".

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

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

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

  • 确定由客户端和服务器之间通用的字节(2)表示的任意"协议"ID,用于过滤掉不适合我的应用程序的消息.

客户

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

服务器

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

对于向另一个方向发送的消息,我需要反过来做同样的事情.

我不禁感到我错过了一些东西,并且不太了解数据包分段的含义.有人可以澄清/指出更好的资源吗?

use*_*421 5

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

不必要.

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

不正确.IP标头是20个字节,而不是60个字节,因此总标头是28个字节.这让你留下了576-28 = 548,但通常被包围的数字是534.

  • 发送超过这个可能会导致碎片

是.

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

不正确.碎片完全在IP级别处理.UDP中的碎片问题是丢失的碎片没有ACK /重传机制,因此丢失的碎片意味着整个数据报丢失.你看到的是整个UDP数据报,或者什么都没有.

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

是.WR Stevens,Unix网络编程,第一卷中给出了一种简单的ACK /重试方案.