我应该如何使用 AsynchronousServerSocketChannel 来接受连接?

2022-09-02 04:26:00

我想使用Java 7和NIO 2编写一个异步服务器。

但是我应该如何使用 AsynchronousServerSocketChannel 呢

例如,如果我从以下方面开始:

final AsynchronousServerSocketChannel server = 
    AsynchronousServerSocketChannel.open().bind(
        new InetSocketAddress(port));

然后当我这样做时,程序终止,因为该调用是异步的。如果我把这个代码放在一个无限循环中,就会抛出一个。server.accept()AcceptPendingException

关于如何使用 编写一个简单的异步服务器的任何建议 ?AsynchronousServerSocketChannel

这是我的完整示例(类似于 JavaDoc 中的示例):

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class AsyncServer {

    public static void main(String[] args) {
        int port = 8060;
        try {
            final AsynchronousServerSocketChannel server = 
                    AsynchronousServerSocketChannel.open().bind(
                            new InetSocketAddress(port));

            System.out.println("Server listening on " + port);

            server.accept("Client connection", 
                    new CompletionHandler<AsynchronousSocketChannel, Object>() {
                public void completed(AsynchronousSocketChannel ch, Object att) {
                    System.out.println("Accepted a connection");

                    // accept the next connection
                    server.accept("Client connection", this);

                    // handle this connection
                    //TODO handle(ch);
                }

                public void failed(Throwable exc, Object att) {
                    System.out.println("Failed to accept connection");
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

答案 1

您走在正确的轨道上,从完成的回调中调用 accept() 以接受更多连接应该可以正常工作。

防止线程终止的一种简单(但丑陋)方法是简单地循环,直到线程中断。

// yes, sleep() is evil, but sometimes I don't care
while (true) {
    Thread.sleep(1000);
}

一种更干净的方法是使用。例如:AsynchronousChannelGroup

AsynchronousChannelGroup group = AsynchronousChannelGroup.withThreadPool(Executors
            .newSingleThreadExecutor());
AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open(group).bind(
            new InetSocketAddress(port));

// (insert server.accept() logic here)

// wait until group.shutdown()/shutdownNow(), or the thread is interrupted:
group.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);

您可以调整线程的处理方式,有关详细信息,请参阅异步通道组 API 文档


答案 2

如果在同一线程中要执行其他操作,则使用异步接受很有用。在你的情况下,你没有做别的事情,所以我会使用

while(true) {
    AsynchronousSocketChannel socket = server.accept().get();
    System.out.println("Accepted " + socket);
    socket.close();
}

推荐