[Android] Java NIO (New I/O) `Selector` class to implement non-blocking Socket monitoring

If you don’t want to use a loop to monitor client connections and data, you can use the Java NIO (New I/O) classSelector to implement non-blocking Socket monitoring. The Selector class provides a mechanism to select a set of channels that are already ready, so that you don't need to use loops to wait for connections and data.

The following is sample code using the Selector class:

private ServerSocketChannel serverSocketChannel;
private Selector selector;

private void startServer() throws IOException {
    
    
    serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.configureBlocking(false);
    serverSocketChannel.socket().bind(new InetSocketAddress(8888));

    selector = Selector.open();
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    while (true) {
    
    
        int readyChannels = selector.select();
        if (readyChannels == 0) {
    
    
            continue;
        }

        Set<SelectionKey> selectedKeys = selector.selectedKeys();
        Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

        while (keyIterator.hasNext()) {
    
    
            SelectionKey key = keyIterator.next();

            if (key.isAcceptable()) {
    
    
                handleAcceptableKey(key);
            } else if (key.isReadable()) {
    
    
                handleReadableKey(key);
            }

            keyIterator.remove();
        }
    }
}

private void handleAcceptableKey(SelectionKey key) throws IOException {
    
    
    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
    SocketChannel clientChannel = serverChannel.accept();
    clientChannel.configureBlocking(false);
    clientChannel.register(selector, SelectionKey.OP_READ);
    Log.d("Server", "设备已连接");
}

private void handleReadableKey(SelectionKey key) throws IOException {
    
    
    SocketChannel channel = (SocketChannel) key.channel();
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    int bytesRead = channel.read(buffer);

    if (bytesRead == -1) {
    
    
        channel.close();
        Log.d("Server", "设备已断开连接");
        return;
    }

    buffer.flip();
    byte[] data = new byte[buffer.limit()];
    buffer.get(data);
    String receivedData = new String(data);
    Log.d("Server", "接收到数据:" + receivedData);

    // 处理接收到的数据

    // 回复客户端
    ByteBuffer responseBuffer = ByteBuffer.wrap(("已接收到数据:" + receivedData).getBytes());
    channel.write(responseBuffer);
}

In the above code, we first create an ServerSocketChannel object and configure it in non-blocking mode. We then bind ServerSocketChannel to the specified port and register it with Selector to listen for client connections.

In thewhile loop, we use the selector.select() method to select the ready channel. If there are no ready channels, we can continue to wait. Once a channel is ready, we use the selector.selectedKeys() method to get the selected set of keys and use an iterator to iterate over the keys.

In the iterator loop, we determine whether the channel can accept connections or read data based on the type of key. If it is a channel that can accept connections, we use the handleAcceptableKey() method. If it is a channel that can read data, we use the handleReadableKey() method to process it.

In thehandleAcceptableKey() method, we use the serverChannel.accept() method to accept the client connection and register the client channel to Selector in order to monitor the data sent by the client.

In thehandleReadableKey() method, we first read the data sent by the client and store it inByteBuffer. If the number of bytes read is -1, it means the client is disconnected, we close the channel and print "Device Disconnected" in the log. If valid data is read, we can process the data in the code and send a reply to the client through the channel.

Please note that this is just a simple example code usingSelector. You need to make appropriate modifications and optimizations according to your actual needs.

Hope this solves your problem!

Guess you like

Origin blog.csdn.net/gao511147456/article/details/134887878