Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何避免使用Java ServerSocket阻塞?_Java_Sockets_Concurrency_Nonblocking - Fatal编程技术网

如何避免使用Java ServerSocket阻塞?

如何避免使用Java ServerSocket阻塞?,java,sockets,concurrency,nonblocking,Java,Sockets,Concurrency,Nonblocking,我正在使用一个套接字侦听器,它必须在两个端口上侦听两种类型的数据(端口80和端口81)。这些数据与对数据执行的操作非常相似,只是因为它们到达不同的端口而有所不同。我继续使用Java的ServerSocket类编写了一个实现,但后来才意识到ServerSocket类的accept()方法是block,我的实现无法承受。所以现在我想用JavaNIO实现同样的功能,但是在看过一些教程之后,我觉得我比我是如何开始的更困惑。如果这里有人能带我走过整个过程,即使是伪代码或JU技术的“下一步做什么”,那就太好

我正在使用一个套接字侦听器,它必须在两个端口上侦听两种类型的数据(端口80和端口81)。这些数据与对数据执行的操作非常相似,只是因为它们到达不同的端口而有所不同。我继续使用Java的ServerSocket类编写了一个实现,但后来才意识到ServerSocket类的accept()方法是block,我的实现无法承受。所以现在我想用JavaNIO实现同样的功能,但是在看过一些教程之后,我觉得我比我是如何开始的更困惑。如果这里有人能带我走过整个过程,即使是伪代码或JU技术的“下一步做什么”,那就太好了。 这就是我计划实现的目标

通过调用2个类似的线程,在2个端口上进行监听(无阻塞) 来自某个网络位置的远程设备连接、发送数据,然后断开连接

我认为,如果只知道如何使用NIO设置服务器以侦听端口(比如本地主机上的端口80),其余的都很容易实现


当您需要扩展到数千个同时连接时,需要使用NIO

否则,我建议使用多线程。对于每个端口(及其相应的
ServerSocket
),创建一个在循环中调用
accept()
的线程。这些调用将被阻止,但这没关系,因为其他线程正在运行,负责处理任何可用的任务

接受新的
套接字时,创建另一个专用于该连接的线程。它取决于应用程序,但通常该线程将从套接字读取(阻塞操作),并执行请求的操作,将结果写回套接字

这种架构将扩展到大多数桌面平台上的数百个连接。而且编程模型相当简单,只要每个连接都是自包含的并且独立于其他连接(这避免了并发问题)。引入NIO将提供更大的可伸缩性,但需要大量的复杂性。

许多框架(如和)都是基于Java NIO实现的,以促进非阻塞IO编程。我强烈建议他们让你的NIO编程成为一种乐趣,而不是一场噩梦。它们适合你的问题


此外,尝试在传输消息大小和编码/解码(序列化/反序列化)性能方面使用有效的协议。这是一个可靠的解决方案。还可以看看和。它们可能会很有帮助。

这里有一个小例子来开始使用NIO

它是一个服务器,监听端口80和81,并打印标准输出上接收到的所有内容。接收到以
CLOSE
开头的数据包后,连接关闭;在收到以
QUIT
开头的数据包后,整个服务器将关闭。缺少发送部分和错误处理可能会更好一些。:-)


没有真正回答这个问题:使用NIO的套接字侦听器
public static void main() throws IOException {
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    Selector selector = Selector.open();

    ServerSocketChannel server1 = ServerSocketChannel.open();
    server1.configureBlocking(false);
    server1.socket().bind(new InetSocketAddress(80));
    server1.register(selector, OP_ACCEPT);

    ServerSocketChannel server2 = ServerSocketChannel.open();
    server2.configureBlocking(false);
    server2.socket().bind(new InetSocketAddress(81));
    server2.register(selector, OP_ACCEPT);

    while (true) {
        selector.select();
        Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
        while (iter.hasNext()) {
            SocketChannel client;
            SelectionKey key = iter.next();
            iter.remove();

            switch (key.readyOps()) {
                case OP_ACCEPT:
                    client = ((ServerSocketChannel) key.channel()).accept();
                    client.configureBlocking(false);
                    client.register(selector, OP_READ);
                    break;
                case OP_READ:
                    client = (SocketChannel) key.channel();
                    buffer.clear();
                    if (client.read(buffer) != -1) {
                        buffer.flip();
                        String line = new String(buffer.array(), buffer.position(), buffer.remaining());
                        System.out.println(line);
                        if (line.startsWith("CLOSE")) {
                            client.close();
                        } else if (line.startsWith("QUIT")) {
                            for (SelectionKey k : selector.keys()) {
                                k.cancel();
                                k.channel().close();
                            }
                            selector.close();
                            return;
                        }
                    } else {
                        key.cancel();
                    }
                    break;
                default:
                    System.out.println("unhandled " + key.readyOps());
                    break;
            }
        }
    }
}
import static java.nio.channels.SelectionKey.*;