繁体   English   中英

使用UDP套接字的多个sendto()

[英]Multiple sendto() using UDP socket

我有一个网络软件,它使用UDP与同一程序的其他实例进行通信。 出于不同的原因,我必须在这里使用UDP。

我最近遇到了通过UDP发送大量数据的问题,并且必须实现一个碎片系统来将我的消息拆分成小数据块。 到目前为止,它运行良好但我现在遇到一个问题,当我必须发送大量的数据块。

我有以下算法:

  1. 将消息拆分为小数据块(大约1500字节)
  2. 迭代数据块列表,并为每个列表使用sendto()发送它

但是,当我发送大量数据块时,接收器只获得前6个消息。 有时它会错过第六名并获得第七名。 这取决于。

无论如何, sendto()总是表示成功。 当我通过环回接口(127.0.0.1)测试我的软件但从未通过我的LAN网络测试我的软件时,总会发生这种情况。

如果我添加类似std::cout << "test" << std::endl; sendto()之间然后接收每一帧。

我知道UDP允许数据包丢失,并且我的帧可能由于很多原因而丢失,我想它与我发送数据块的速率有关。

这里的方法是什么?

  • 实现一些确认机制(就像TCP)似乎有点矫枉过正。
  • sendto()之间添加一些任意等待时间很难看,可能会降低性能。
  • 增加(如果可能)接收器UDP内部缓冲区? 我甚至不知道这是否可行。
  • 别的什么?

我真的需要你的意见。

非常感谢。

所需的其他信息

必须使用UDP的原因是因为我有几个约束:

  1. TCP在NAT遍历中不能很好地工作(至少没有特定的配置)
  2. 有些消息可能会丢失。 有些人不能。
  3. 邮件传递顺序无关紧要。

如果在仅发送6或7个数据包后通过环回接口丢失数据包,则听起来可能是您的接收缓冲区太小。 您可以使用SO_RCVBUF选项使用setsockopt增加大小。 但是,如果您要发送1500个字节,那么如果这确实是问题,则意味着接收缓冲区仅为大约9K(或者更可能是8K,但这似乎是一个相当小的默认值)。 我相信在Windows上默认的接收缓冲区是16K。

即使假设增加接收缓冲区有帮助,您仍然必须解决其他人提到的问题。 还有一些需要考虑的事情是尝试动态确定最大数据包大小以避免碎片。 此外,可以有意义地使得在acks之间发送的分组大小和分组数量可手动配置。

调用UDP不可靠是一种简化,它试图将TCP作为所有网络弊病的灵丹妙药。 同样,将TCP定义为可靠也是错误的。 虽然TCP确实存在尝试确保数据传输的机制,但导致UDP数据包故障的许多故障也会导致TCP失败。

例如,硬件网络故障将对UDP和TCP数据包产生相同的影响。 如果故障仍然存在,那么TCP将无法像UDP一样通过。 实际上在这种情况下,TCP的缺点在于它将尝试更长时间地完成丢失的原因。 现在,如果您通过互联网发送数据,TCP具有一些优势,因为无法预定义发送数据包的路由。 但是,对于通过LAN发送数据,UDP非常适合。 如果您的数据包未到达目的地,则表示需要更正的硬件故障。 TCP在这里没有帮助。

在选择协议时,您还必须了解您的数据。 如果您的数据是瞬态的,例如从传感器读取数据,则使用UDP over TCP更有意义。 如果在这种情况下数据包丢失,那么由于另一个数据包将很快出现,因此它没什么意义。 另一方面,TCP将退回并重试。 到数据到达时,它已经过时了。

事实是TCP是专为流数据而设计的。 在这种情况下,重要的是所有数据包都可靠且有序地到达。 UDP用于分组数据,并且对于这种类型的数据,UDP是完全可接受的,因为可靠,具有较少的开销并且更快地检测和从网络故障中恢复。

实现的确认机制,听起来像是你需要做什么 这样,您可以确保一次不超过N个数据包“正在进行中”,并且您可以重新传输未经确认太长时间的数据包。

您应该实现确认和重传。 每N个数据包需要例如acks,并在重传缓冲区中保留N个数据包。

(也许你可以从rudp获得一些想法,或者通过UDP实现Il

UDP不可靠,也不提供流量控制。 简而言之,你会不时地丢失数据包 - 特别是如果你快速发送数据 - 如果没有足够的空间,内核或其间的任何路由器/交换机将丢弃数据包 - 并且你可以采用不用的魔法发生。

无论如何,sendto()总是表示成功。 当我通过环回接口(127.0.0.1)测试我的软件但从未通过我的LAN网络测试我的软件时,总会发生这种情况。

如果我添加类似std :: cout <<“test”<< std :: endl; 在sendto()之间然后接收每一帧。

听起来你的接收缓冲区太小了。

一些忠告:

  1. 增加接收缓冲区。 setsockopt SO_RCVBUF
  2. 让应用程序决定是否重传丢包。
  3. 确保有效负载符合MTU,这意味着有效负载+ HEADER <= 1500,以避免IP碎片。

TCP存在以解决这种问题。 为什么TCP不是一个选项? 您将不得不解决所有相同的问题,并最终得到相同的解决方案,只是没有数十年的TCP堆栈研究,开发和调试的好处。

如果你真的必须使用UDP,首先要问的问题是,你有什么愿意放弃TCP的保证? 您是否乐于接收无序的数据包? 丢失一定比例的数据包可以吗? 你能处理重复数据包的到来吗? 这些问题的答案将有希望导致设计。

在不知道你的具体细节的情况下,用一个简单的“做这个,你会没事的”来回答你的问题是不可能的,当然除了“做TCP,你会没事”。

UDP传输数据报,并且不可靠。

TCP传输数据流,并且是可靠的。

您想要的似乎是基于数据报,但可靠。 因此,您需要在UDP或TCP上构建一些东西来为您提供。 我确信在UDP上有完整的协议规范可以提供。 您只需要找到并实现它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM