简体   繁体   English

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

[英]How should I use AsynchronousServerSocketChannel for accepting connections?

I would like to write an asynchronous server using Java 7 and NIO 2. 我想用Java 7和NIO 2编写一个异步服务器。

But how should I use AsynchronousServerSocketChannel ? 但是我应该如何使用AsynchronousServerSocketChannel

Eg if I start with: 例如,如果我开始:

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

Then when I do server.accept() , the program terminates because that call is asynchronous . 然后,当我执行server.accept() ,程序终止,因为该调用是异步的 And if I put that code in an infinite loop, an AcceptPendingException is thrown. 如果我将该代码放在无限循环中,则抛出AcceptPendingException

Any suggestions on how to write a simple asynchronous server using AsynchronousServerSocketChannel ? 有关如何使用AsynchronousServerSocketChannel编写简单异步服务器的任何建议?

Here is my full example (similar to the example in the JavaDoc): 这是我的完整示例(类似于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();
        }
    }
}

You are on the right track, calling accept() from the completed callback in order to accept more connections should work. 你在正确的轨道上,从完成的回调中调用accept()以接受更多连接应该工作。

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 . 更简洁的方法是使用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. 您可以调整线程的处理方式,有关详细信息,请参阅AsynchronousChannelGroup API文档

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM