Question

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
Was it helpful?

Solution

After putting stuff into a Buffer, or reading stuff into it you have to flip the buffer to write or get the data from it. Check the flip() method in the Buffer class. The docs say

Flips this buffer. The limit is set to the current position and then the position is set to zero. If the mark is defined then it is discarded. After a sequence of channel-read or put operations, invoke this method to prepare for a sequence of channel-write or relative get operations.

So adding a buffer.flip() after the put should do the trick :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top