0

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

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

4

0 回答 0