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

发布于 2024-12-27 19:37:09 字数 1999 浏览 0 评论 0原文

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

I would like to write an asynchronous server using Java 7 and NIO 2.

But how should I use AsynchronousServerSocketChannel?

E.g. 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. And if I put that code in an infinite loop, an AcceptPendingException is thrown.

Any suggestions on how to write a simple asynchronous server using AsynchronousServerSocketChannel?

Here is my full example (similar to the example in the 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();
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

少钕鈤記 2025-01-03 19:37:09

您走在正确的轨道上,从已完成的回调中调用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 文档 了解更多信息。

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.

情话难免假 2025-01-03 19:37:09

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

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

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();
}
枕头说它不想醒 2025-01-03 19:37:09

另一种选择是让您的 main 方法在返回之前等待信号。然后,如果您有某种外部关闭命令,您只需通知该信号,主线程就会关闭。

private static final Object shutdownSignal = new Object();

public static void main(String[] args) {

    ...

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

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!
        }
    }
}
烂柯人 2025-01-03 19:37:09

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

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

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();
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文