1

I am using SocketChannel to communicate with remote server. I send data using socketChannel.write() with no errors and exceptions, however, the server log indicates no data was received; client tcp traffic monitor also shows that the string message in the ByteBuffer was not sent.

Could anyone give me a hint why this is the case? Thank you!

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
4

1 回答 1

6

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

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

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

于 2014-02-23T05:01:52.557 回答