Java 使用NIO的非阻塞客户端

Java 使用NIO的非阻塞客户端,java,client,nio,nonblocking,Java,Client,Nio,Nonblocking,我是NIO新手,需要使用下一个api创建简单的非阻塞客户端: void start(); void send(String msg); void stop(); Start方法应为指定的主机和端口创建连接。 stop方法应停止客户端并释放连接。 send应该将消息发送到服务器 因此,我阅读了文档并创建了简单客户端: public class NonBlockingNIOClient { private DatagramChannel channel; public fina

我是NIO新手,需要使用下一个api创建简单的非阻塞客户端:

void start();
void send(String msg);
void stop();
Start方法应为指定的主机和端口创建连接。 stop方法应停止客户端并释放连接。 send应该将消息发送到服务器

因此,我阅读了文档并创建了简单客户端:

public class NonBlockingNIOClient {

    private DatagramChannel channel;

    public final static int MAX_PACKET_SIZE = 65507;

    private static final Logger LOGGER = LoggerFactory.getLogger(NonBlockingNIOStatsDClient.class);

    public NonBlockingNIOStatsDClient(String host, int port) {
      this.host = host;
      this.port = port;
    }


    public void start() {
        try {
            channel = DatagramChannel.open();
            channel.configureBlocking(false);
            channel.connect(new InetSocketAddress(getHost(), getPort()));
            while (!channel.isConnected()) {
                LOGGER.debug("still connecting");
            }

            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    while(channel.isConnected()) {
                    }
                }
            });
            thread.start();

        } catch(IOException e) {
            throw new ClientException("Failed to start client", e);
        }
    }

    public void stop() {
        try {
            channel.disconnect();
        } catch(IOException e) {
            throw new StatsDClientException("Failed to stop client", e);
        }
    }

    @Override
    public void send(String msg) {
        LOGGER.debug("send: {}", msg);
        Validate.notBlank(msg, "message to sand cannot be blank");

        ByteBuffer buf = ByteBuffer.allocate(MAX_PACKET_SIZE);
        buf.clear();
        buf.put(msg.getBytes());
        buf.flip();

        try {
            channel.write(buf);
        } catch(IOException e) {
            getErrorHandler().handle(e);
        }
    }
}
我是如何从
channel.configureBlocking(false)的文档中理解的不保证来自通道的写入方法将在非阻塞模式下工作。我想我需要使用选择器来实现非阻塞行为。但当我下一步要做的时候:

            Selector selector = null;
            try {
                selector = Selector.open();
                channel.register(selector, SelectionKey.OP_WRITE);
                while(channel.isConnected()){
                    selector.select();
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while(iterator.hasNext())
                    {
                        SelectionKey key = iterator.next();


                        if(key.isWritable())
                        {
                            //do send
                        }
                        iterator.remove(); 
                    }
                }
                selector.close();
            }  
Selector=null;
试一试{
选择器=selector.open();
通道寄存器(选择器、选择键、操作写入);
while(channel.isConnected()){
selector.select();
迭代器迭代器=选择器。selectedKeys()。迭代器();
while(iterator.hasNext())
{
SelectionKey=iterator.next();
if(key.isWritable())
{
//派
}
iterator.remove();
}
}
selector.close();
}  

在这种情况下,客户端不响应
send()
方法,因为客户端在(channel.isConnected())
时被
阻止。您对我如何使start方法可用并同时使用选择器有何建议

“while(channel.isConnected())”上显然毫无意义的自旋循环最初的目的是什么?把它取下来,好的。所以,我认为我需要使用队列,send()方法将把要发送的消息放入队列中,而“if(key.iswriteable()){}”块中的一些逻辑将从队列中获取消息并将其发送到服务器。没关系,这种方法有意义吗?我宁愿问你为什么你认为你需要在客户机中使用NIO。除非你处理的是多个服务器,否则就没有意义了。我只是想了解如何实现这样的客户端。不,我不知道将使用多少台服务器,也不知道使用了哪种技术(I/O或NIO)来实现服务器。我只是想知道它一般如何实现,以何种方式实现,目前仅此而已。我强烈建议您首先使用
java.net
,然后再看看您是否需要对它做更多的工作。