使用NIO的非阻塞客户端

时间:2013-10-25 10:29:53

标签: java client nio nonblocking

我是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())阻止。您有什么建议我可以使用启动方法并同时使用选择器。

0 个答案:

没有答案