Java中的非阻塞UDP I/O与阻塞UDP I/O的区别

18

非阻塞 TCP/IP 的 SocketChannelSelector 在 NIO 中帮助我用少量的线程处理很多 TCP/IP 连接。但是 UDP 的 DatagramChannels 呢?(我必须承认我对 UDP 不是很熟悉。)

即使 DatagramChannel 没有在阻塞模式下运行,UDP 发送操作似乎也不会阻塞。真的存在因拥塞或类似原因而导致 DatagramSocket.send(DatagramPacket) 阻塞的情况吗?我真的很好奇在生产环境中是否存在这样的情况以及可能存在哪些情况。

如果 DatagramSocket.send(DatagramPacket) 实际上并没有阻塞,并且我不会使用连接的 DatagramSocket 并且仅绑定到一个端口,那么使用非阻塞模式和 SelectorDatagramChannel 没有任何优势吗?

3个回答

17

我有一段时间没有使用Java的DatagramSockets、Channels等技术了,但我仍然能够为您提供一些帮助。

UDP协议不像TCP那样建立连接。相反,它只是发送数据后就忘记了。如果确保数据已经到达非常重要,那就由客户端来负责。因此,即使您处于阻塞模式,您的发送操作也只会阻塞直到缓冲区被清空为止。由于UDP对网络一无所知,它会在最早的机会将数据写出,而不会检查网络速度或是否实际到达目标地址。因此,在您看来,通道似乎立即准备好了可以继续发送数据。


1
如果UDP套接字上的写入速度过快,导致内核缓冲区被淹没,会发生什么? - trustin
你的(用户级别)写操作会阻塞,直到内核刷新该套接字的发送缓冲区。 - JLR
8
阻塞和非阻塞UDP套接字之间存在明显的区别,就像阻塞和非阻塞TCP套接字之间的区别一样。我写了一个简单的PoC客户端,并确认非阻塞UDP通道的send()函数经常返回0,而阻塞的则永远不会返回0。谢谢! - trustin

10

UDP不会阻塞(只有在将数据传输到操作系统时才会阻塞),这意味着如果下一个跳/交换机/计算机无法缓冲UDP数据包,它会将其丢弃。在某些情况下,这可能是希望的行为,但这是您需要了解的情况。

此外,UDP也不能保证:

  • 按发送顺序传递数据包。
  • 不会分割大型数据包。
  • 转发数据包通过交换机。通常情况下,UDP在交换机之间的转发被关闭。

然而,UDP支持多播,因此可以将同一数据包传递给一个或多个主机。发送方不知道是否有任何人接收数据包。

UDP的棘手之处在于它大部分时间都可以正常工作,但有时会以非常难以复制的方式严重失败。因此,即使进行了几次测试并且看起来好像没有问题,您也不应该假设它是可靠的。


0

非阻塞UDP在接收端大多数情况下非常有用。 数据包的发送只能由于本地环境而延迟:例如本地流量整形工具(如“游戏网络卡”)会优先处理游戏流量而不是其他流量源,或者过载的网络卡(这种情况不太可能发生)会延迟数据包的发送。一旦离开系统,数据包离开本地接口后,就不再是应用程序的关注点。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接