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

时间:2013-12-01 16:20:49

标签: .net sockets networking udp

多年来我一直使用TCP做很多事情并且理解得很好。我现在要求使用UDP。

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

在这种情况下,时间(参数变化时)很重要,请求更改和实施的客户端之间的延迟必须尽可能低。

我已经doing a lot of reading而且我还没有"得到它&#34 ;

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

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

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

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

客户端

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

服务器

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

对于向另一个方向发送的消息,我需要反向完成相同的操作。

我无法帮助感觉我错过了某些内容,并且不太了解数据包碎片的含义。有人可以澄清/指出更好的资源吗?

2 个答案:

答案 0 :(得分:5)

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

不一定。

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

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

  
      
  • 发送更多内容可能会导致碎片化
  •   

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

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

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

是。 W.R. Stevens给出了一个简单的ACK /重试方案, Unix网络编程,第一卷。

答案 1 :(得分:2)

  

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

没有

  

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

'可靠发送'意味着不同的东西到不同的层次。

  

发送更多内容可能会导致碎片

经济实事求是。

  

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

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

子问题:太宽泛了,但听起来你应该使用TCP代替。

相关问题