使用NIO和UDP有什么好处?

12

NIO 和 TCP 对于许多连接来说是一个很好的组合。由于每个新客户端都需要打开一个新连接,因此每个客户端通常需要自己的线程来进行阻塞式 I/O 操作。NIO 解决了这个问题,它允许在数据可用时进行读取,而不是一直阻塞等待数据。但是 UDP 呢?

我的意思是,无连接的 UDP 由于其协议设计方式(发送并忘记)而没有与 TCP 相关的阻塞性质。如果我决定向某个地址发送一些数据,那么它将立即执行,没有延迟(在服务器端)。同样,如果我想读取数据,我只需从不同来源接收各个数据包。我不需要使用许多线程建立许多到不同地方的连接来处理它们。

那么,NIO 和选择器如何增强 UDP?更具体地说,什么情况下会优先使用带有 NIO 的 UDP 而不是 java.net 包中旧的方法?


不是回答你的问题,但你应该先检查NIO是否比TCP更快或更好-http://mailinator.blogspot.in/2008/02/kill-myth-please-nio-is-not-faster-than.html http://paultyma.blogspot.in/2008/03/writing-java-multithreaded-servers.html - user93353
2个回答

9
DatagramSocket.receive(...)方法是一种阻塞操作。所以,例如,如果您有一个线程试图处理来自N个不同套接字的数据包,则需要使用NIO和选择器。同样,如果线程必须在检查新数据包与其他活动之间进行多路复用,则可以这样做。
如果没有这些或类似要求,则选择器将无法帮助。但TCP情况也是如此。如果您不需要它们,则不应使用TCP选择器,因为它可能会增加额外的系统调用。
(在Linux中,在数据报案例中,您将执行select系统调用,然后是recv...而不仅仅是recv。)

但是,如果您只处理一个DatagramSocket,那么无论它们来自哪台计算机,receive方法是否会立即读取数据包?

如果您正在侦听所有人的数据包,则是的。如果您有不同的套接字来自不同的计算机,则不是。

至于TCP评论,有时光选择器的使用仅仅由于每个阻塞式TCP服务器都需要成千上万个线程,这会消耗大量资源。

我们没有讨论过这种情况。但是,确实如此。如果您有数千个线程阻塞在UDP接收上,则情况也是如此。
我的观点是,如果您没有大量线程,或者如果线程阻塞并不重要,则NIO无法帮助。事实上,它可能会降低性能。

但是,如果您只处理一个DatagramSocket,那么receive方法是否会立即读取到达的数据包,而不管它们来自哪台计算机?至于TCP评论,有时使用选择器仅仅是因为拥有数千个线程非常耗费资源,这对于阻塞式TCP服务器是必需的。 - Martin Tuskevicius
如果它们到达的话,那就是一个阻塞操作。通过select()循环将调度从操作系统转移到应用程序也非常耗费资源,并且不一定公平。需要记住的是,select()是在线程甚至不存在之前设计的,而替代方案是多个进程。对这个答案点赞。 - user207421
如果服务器端有一个单独的UDP套接字,被多个客户端使用,那么使用阻塞IO和专用线程池来处理数据包会更有效率吗? - ka4eli
1
不一定。您可以拥有一个线程池,每个线程都执行“接收”调用。这可能会更快-减少上下文切换。建议:如果您真的关心,请尝试两种方法并测量性能差异。 - Stephen C
1
是的,它应该处理大量的请求。这种方法有什么问题吗? - ka4eli
显示剩余2条评论

4

NIO(New Input/Output)完全消除了线程的必要性。它让你可以在一个线程内处理所有客户端,包括TCP和UDP客户端。

无连接 UDP 没有 TCP 的阻塞特性。

这并不是真的。接收仍然会阻塞,至少在理论上发送也会。


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