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

我想用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() { 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(); } } } 

你是在正确的轨道上,从完成的回调中调用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); 

您可以调整线程的处理方式,有关详细信息,请参阅AsynchronousChannelGroup API文档 。

如果您在同一个线程中还有其他事情要做,那么使用异步接受非常有用。 在你的情况下,你没有做其他事情所以我会使用

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

另一种方法是让主方法在返回之前等待信号。 然后,如果你有某种外部关机命令,你只需通知信号,主线程关闭。

 private static final Object shutdownSignal = new Object(); public static void main(String[] args) { ... synchronized (shutdownSignal) { try { shutdownSignal.wait(); } catch (InterruptedException e) { // handle it! } } } 

使用倒计时锁存器,如下例所示

  final AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open(); InetSocketAddress address = new InetSocketAddress(port); serverChannel.bind(address); final CountDownLatch latch = new CountDownLatch(1); serverChannel.accept(null, new CompletionHandler() { @Override public void completed(final AsynchronousSocketChannel channel, Object attachment) { serverChannel.accept(null, this); } }); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); Thread.currentThread().interrupt(); }