How should I use AsynchronousServerSocketChannel for accepting connections?

三世轮回 提交于 2019-11-29 21:02:13

You are on the right track, calling accept() from the completed callback in order to accept more connections should work.

A simple (but ugly) way to prevent the thread from terminating is simply to loop until the thread is interrupted.

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

A cleaner way is to use AsynchronousChannelGroup. For instance:

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);

You can tune how threads are handled, see the AsynchronousChannelGroup API docs for more information.

Using asynchronous accept is useful if you have something else to do in the same thread. In you case, you are not doing something else so I would use

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

Another alternative is to have your main method wait on a signal before returning. Then if you have some kind of external shutdown command, you just notify the signal and the main thread shuts down.

private static final Object shutdownSignal = new Object();

public static void main(String[] args) {

    ...

    synchronized (shutdownSignal) {
        try {
            shutdownSignal.wait();
        }
        catch (InterruptedException e) {
            // handle it!
        }
    }
}

Use count down latch like the following example

    final AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open();
    InetSocketAddress address = new InetSocketAddress(port);
    serverChannel.bind(address);
    final CountDownLatch latch = new CountDownLatch(1);
    serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {
@Override
        public void completed(final AsynchronousSocketChannel channel, Object attachment) {
            serverChannel.accept(null, this);
                        }

});
try {
        latch.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
        Thread.currentThread().interrupt();
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!