SocketChannel write()返回时没有错误但实际上没有发送数据

时间:2014-02-23 04:52:25

标签: java sockets nio socketchannel

我正在使用SocketChannel与远程服务器通信。我使用socketChannel.write()发送数据,没有错误和异常,但是,服务器日志表明没有收到数据; client tcp traffic monitor还显示ByteBuffer中的字符串消息未发送。

有人能给我一个暗示为什么会这样吗?谢谢!

public class Client implements Runnable {
    SocketChannel socketChannel;
    Selector selector;
    SelectionKey key;
    ByteBuffer inbuf, outbuf;
    int id;
    @Override
    public void run() {
    try {
        // prepare inbuf and outbuf
        inbuf = ByteBuffer.allocate(10000);
        outbuf = ByteBuffer.allocate(10000);

        // prepare a socket channel for communication
        socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress("<remote server ip>", ));
        selector = Selector.open();
        socketChannel.configureBlocking(false);
        key = socketChannel.register(selector, SelectionKey.OP_READ
                | SelectionKey.OP_WRITE);

        while (selector.select() > 0) {

            if (key.isReadable()) {
                // read from channel when server sends data
                read();
            }

            if (key.isWritable()) {
                // write
                Random r = new Random(500);
                write("b", r.nextInt(), r.nextInt());
                for (int i = 0; i < 10; i++) {
                    // write a message to server after 1 second
                    Thread.sleep(1000);
                    write("m", r.nextInt(), r.nextInt());
                }
                write("e", r.nextInt(), r.nextInt());
            }
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

private void write(String action, int x, int y) throws IOException {
    String msg = String.format("%s:%d:%d:%d", action, id, x, y);
    int r=outbuf.remaining();

    outbuf.put(msg.getBytes());
    int rBytes = outbuf.remaining();
    boolean connected = socketChannel.isConnected();
    Socket sock = socketChannel.socket();

    if (connected && sock.isConnected() && !sock.isOutputShutdown())
>>>>>>>>>>    socketChannel.write(outbuf);
    else
        System.out.println("Connection broken!");

    System.out.printf("Client %d told server:%s\n", id, msg);
    //outbuf.clear();
}

   ... //read omitted here

1 个答案:

答案 0 :(得分:6)

将内容放入缓冲区或读取内容后,您必须翻转缓冲区以写入或从中获取数据。检查Buffer类中的flip()方法。文档说

  

翻转此缓冲区。限制设置为当前位置,然后位置设置为零。如果定义了标记,则将其丢弃。   在一系列通道读取或放置操作之后,调用此方法以准备一系列通道写入或相对获取操作。

因此在put之后添加一个buffer.flip()应该可以解决问题:)