【发布时间】: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