java - 即使没有来自客户端的连接,选择器也会无限循环

标签 java selector nio

我是 Java NIO 的新手,在阅读了一些教程之后,我尝试自己编写一个简单的 NIO 服务器和客户端。 我的服务器只是做了一件简单的事情,就是从客户端监听并打印到控制台,客户端只连接到服务器并向它发送 3 条消息“Hello”。 问题是我的服务器监听并很好地处理了 3 条消息,之后它应该被阻止并继续监听,但它没有,没有阻止,它在无限循环时运行它。这是我的服务器和客户端:

服务器

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;

public class Server {
    public static void main(String args[]) throws Exception {
        // Create the server socket channel
        ServerSocketChannel server = ServerSocketChannel.open();
        // nonblocking I/O
        server.configureBlocking(false);
        // host-port 8000
        server.socket().bind(new InetSocketAddress(8000));
        System.out.println("Server actives at port 8000");
        // Create the selector
        Selector selector = Selector.open();
        // Recording server to selector (type OP_ACCEPT)
        server.register(selector, SelectionKey.OP_ACCEPT);

        while (selector.select() > 0) {

            // Get keys
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> i = keys.iterator();

            // print 
            System.out.println("[ " + keys.size() + " ]");

            // For each keys...
            while (i.hasNext()) {
                SelectionKey key = (SelectionKey) i.next();
                // Remove the current key
                i.remove();

                // if isAccetable = true
                // then a client required a connection
                if (key.isAcceptable()) {
                    // get client socket channel
                    SocketChannel client = server.accept();
                    // Non Blocking I/O
                    client.configureBlocking(false);
                    // recording to the selector (reading)
                    client.register(selector, SelectionKey.OP_READ);
                    continue;
                }

                // if isReadable = true
                // then the server is ready to read
                if (key.isReadable()) {

                    SocketChannel client = (SocketChannel) key.channel();

                    // Read byte coming from the client
                    int BUFFER_SIZE = 1024;
                    ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
                    try {
                        client.read(buffer);
                    } catch (Exception e) {
                        // client is no longer active
                        e.printStackTrace();
                    }

                    // Show bytes on the console
                    buffer.flip();
                    Charset charset = Charset.forName("ISO-8859-1");
                    CharsetDecoder decoder = charset.newDecoder();
                    CharBuffer charBuffer = decoder.decode(buffer);
                    System.out.println("[" + charBuffer.toString() + "]");
                }
            }
        }
    }
}

这是我的客户:

import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class Client {
    public static void main(String args[]) throws Exception {
        // Create client SocketChannel
        SocketChannel client = SocketChannel.open();

        // nonblocking I/O
        client.configureBlocking(false);

        // Connection to host port 8000
        client.connect(new java.net.InetSocketAddress("127.0.0.1", 8000));

        // Create selector
        Selector selector = Selector.open();

        // Record to selector (OP_CONNECT type)
        SelectionKey clientKey = client.register(selector,
                SelectionKey.OP_CONNECT);

        int counter = 0;
        boolean chk = true;

        // Waiting for the connection
        while (selector.select(500) > 0 && chk) {
            // Get keys
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> i = keys.iterator();

            // For each key...
            while (i.hasNext() && chk) {
                SelectionKey key = (SelectionKey) i.next();

                // Remove the current key
                i.remove();

                // Get the socket channel held by the key
                SocketChannel channel = (SocketChannel) key.channel();

                // Attempt a connection
                if (key.isConnectable()) {

                    // Connection OK
                    System.out.println("Server Found");

                    // Close pendent connections
                    if (channel.isConnectionPending())
                        channel.finishConnect();

                    // Write continuously on the buffer
                    ByteBuffer buffer = null;
                    for (;chk;counter++) {
                        Thread.sleep(1000);
                        buffer = ByteBuffer.wrap(new String(" Client ").getBytes());
                        channel.write(buffer);
                        buffer.clear();

                        if (counter == 2)
                        {
                             chk = false;
                             client.close();
                        }
                    }

                }
            }
        }
    }
}

谁能解释我的代码有什么问题? 提前致谢。

最佳答案

您可能正在从已接受的套接字 channel 中获取源源不断的 EOS-s。您忽略了 read() 的结果。您至少必须检查它是否为 -1,如果是,则关闭 channel 。

关于java - 即使没有来自客户端的连接,选择器也会无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9736057/

相关文章:

java - 来自现有 wsdl 的带有 spring-boot 和 mtom 的 SOAP 服务

java - 自定义流媒体实现

java - 复制文件的文件创建日期java nio

java - 是否可以在 CPU 使用率不高的情况下将 NIO 保持在 OP_WRITE 模式

java - 我需要帮助从方法更新 main 中的数组

Java 还是 Scala 用于新的绿地项目?

javascript - jQuery.is() :first showing different behavior from :last

ios - 如何测试 UIControlEvents 是否已被触发

objective-c - Objective-C中@selector中的多个参数

java - 为什么 PathMatcher 不匹配路径?