【问题标题】:A non-blocking server with java.io带有 java.io 的非阻塞服务器
【发布时间】:2012-11-22 15:58:48
【问题描述】:

大家都知道java IO是blocking,java NIO是non-blocking。在 IO 中,您必须使用每个客户端的线程模式,在 NIO 中,您可以为所有客户端使用一个线程。

现在我的问题是:是否可以使用 Java IO api 进行非阻塞 设计。 (不是蔚来)

我正在考虑这样的模式(显然非常简化);

        List<Socket> li;
        for (Socket s : li) {
            InputStream in = s.getInputStream();
            byte[] data = in.available();
            in.read(data);
            // processData(data); (decoding packets, encoding outgoing packets
        }

另请注意,客户端将始终准备好读取数据。

您对此有何看法?这是否适用于至少应容纳数百个客户端而不会出现重大性能问题的服务器?

【问题讨论】:

  • 您认为这会以何种方式实现非阻塞?
  • 您似乎有正确的想法,即您使用 available 方法模拟非阻塞 I/O 并轮询客户端。但是 EJP 的答案是正确的
  • @JordanKaye 我认为这是非阻塞的,因为我只读取了准备好的字节数

标签: java sockets io


【解决方案1】:

这是可能的,但毫无意义。 java.net 中没有 select(),因此您只能轮询套接字,这意味着在轮询之间休眠,并且您无法确定要休眠多长时间,因此您会睡得比需要的时间更长,因此您将浪费时间,增加延迟等;否则你必须睡很短的时间间隔,从而消耗毫无意义的 CPU。

对于仅有的几百个客户端,不可能反对每个连接使用一个线程的传统方式。

我不知道“客户端将始终准备好读取数据”是什么意思。你无法从服务器上看出这一点,如果它还没有准备好,写入它可能会阻塞,这会彻底破坏你的 applecard。

【讨论】:

  • +1 和 available() 似乎在各个平台上充其量都是古怪的。尝试此恕我直言的最佳方法是使用超时轮询每个套接字(SO_TIMEOUT 套接字选项),这又一次......根本不会比每个线程单个连接解决方​​案更好。
  • '客户端将始终准备好读取数据':意味着有一个无限循环来查找可用数据,并使用工作线程处理它(可能不是很相关,只是一个说明,让你知道服务器不会阻止写入)。感谢您的意见,非常有帮助:)。
  • @Jon 'Ready for reading' 和 'block on writing' 完全不相关。你的说法没有道理。
  • @Jon ...如果套接字发送缓冲区中没有空间,服务器确实会阻止写入,这是由于对等方读取速度比本地主机发送速度慢。