首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么Java的NIO.2中的异步通道需要这些暂停?

为什么Java的NIO.2中的异步通道需要这些暂停?
EN

Stack Overflow用户
提问于 2013-10-07 01:03:27
回答 1查看 2.6K关注 0票数 0

我已经写了最小的例子,但还是太长了,所以让我知道我应该把链接贴到Pastebin上。

服务器:

代码语言:javascript
复制
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class Srv {
    static final int    PORT = 9001;
    static final String HOST = "127.0.0.1";
    public static void runInstance() {
        try (AsynchronousServerSocketChannel asynchronousServerSocketChannel =
                     AsynchronousServerSocketChannel.open()) {
            if (asynchronousServerSocketChannel.isOpen()) {
                asynchronousServerSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 1024);
                asynchronousServerSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
                asynchronousServerSocketChannel.bind(new InetSocketAddress(HOST, PORT));
                System.out.println(String.format("Launched master on %s:%d", HOST, PORT));

                asynchronousServerSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
                    @Override
                    public void completed(AsynchronousSocketChannel result, Void attachment) {
                        asynchronousServerSocketChannel.accept(null, this);
                        try {
                            result.read(ByteBuffer.allocate(1024));
                            System.out.println("Conn from:" + result.getRemoteAddress());
                        } catch (Exception exn) {
                            exn.printStackTrace();
                        } finally {
                            try {
                                result.close();
                            } catch (IOException exn) {
                                exn.printStackTrace();
                            }
                        }
                    }
                    @Override
                    public void failed(Throwable exn, Void attachment) {
                        asynchronousServerSocketChannel.accept(null, this);
                        throw new UnsupportedOperationException("can't accept");
                    }
                });
                System.in.read();
            } else {
                System.out.println("The asynchronous server-socket channel cannot be opened");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

客户端:

代码语言:javascript
复制
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

import static java.lang.Thread.sleep;

public class Wrk {
    static final int    PORT = 9001;
    static final String HOST = "127.0.0.1";
    public static void runInstance() throws InterruptedException {
        sleep(1000); //HERE
        try(AsynchronousSocketChannel asynchronousSocketChannel = AsynchronousSocketChannel.open()) {
            if (asynchronousSocketChannel.isOpen()) {
                asynchronousSocketChannel.setOption(StandardSocketOptions.SO_RCVBUF, 1024);
                asynchronousSocketChannel.setOption(StandardSocketOptions.SO_SNDBUF, 1024);
                asynchronousSocketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
                asynchronousSocketChannel.connect(new InetSocketAddress(HOST, PORT), null,
                    new CompletionHandler<Void, Void>() {
                        @Override
                        public void completed(Void result, Void attachment) {
                            try {
                                System.out.println("Connected to: " + HOST + PORT);
                                asynchronousSocketChannel.read(ByteBuffer.allocate(1024)).get();
                            } catch (Exception exn) {
                                exn.printStackTrace();
                            } finally {
                                try {
                                    asynchronousSocketChannel.close();
                                } catch (IOException exn) {
                                    exn.printStackTrace();
                                }
                            }
                        }

                        @Override
                        public void failed(Throwable throwable, Void o) {
                            System.out.println("Connection cannot be established");
                        }
                    });
                sleep(1000); //AND HERE
            } else {
                System.out.println("The asynchronous socket channel cannot be opened");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

要运行的样板:

代码语言:javascript
复制
public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread srv = new Thread(new Runnable() {
            @Override
            public void run() {
                Srv.runInstance();
            }
        });
        srv.start();
        Thread wrk1 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Wrk.runInstance();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        wrk1.start();
    }
}

因此,如果我有这样的代码,它会给出以下输出:

代码语言:javascript
复制
Launched master on 127.0.0.1:9001
Connected to: 127.0.0.1 9001
Conn from:/127.0.0.1:50415

但是如果我在Srv.runInstance()中删除这些sleep(),我会得到:

代码语言:javascript
复制
Connection cannot be established
Launched master on 127.0.0.1:9001
Conn from:/127.0.0.1:50438

那么,这是否意味着客户端连接到服务器,但服务器拒绝?我不清楚这里发生了什么,文档也很差,所以我不知道去哪里寻找解决方案。

EN

回答 1

Stack Overflow用户

发布于 2013-10-07 01:10:16

我在所发布的代码中看到的唯一睡眠是在Wrk.runInstance中。但是,输出的顺序清楚地说明了发生了什么。您的工作正在尝试在服务器完全初始化之前连接到服务器。正如您在输出中看到的,“连接消息”位于“启动的主节点”之前。

服务器需要一点时间才能启动,因此在没有休眠的情况下,您的客户端正在尝试连接到尚未存在的东西。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19211475

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档