简体   繁体   中英

SocketChannel.write() writing problem

The issue here is I can see that the data is being written out to the socket but it is not ALWAYS being sent.

Here's a code sniplet

ByteBuffer writeBuffer = ByteBuffer.allocate(8192);
writeBuffer.clear();
writeBuffer.put("heartbeat".getBytes());


writeBuffer.flip();
LOG.debug("is connected: " + socketChannel.isConnected());
int bytesWritten = 0;
if (key.isWritable()) {
    while (writeBuffer.hasRemaining()) {
        bytesWritten += socketChannel.write(writeBuffer);
    }
}

I use TCPMon to see if the actual data gets written out to the socket - WHICH it does.

But using WireShark (another network monitoring tool) I cannot see the packet going through the NIC.

Any help would be appreciated

Your code is wrong anyway. If the write returns zero the socket send buffer is full, so you should register OP_WRITE and return to the select loop, rather than waste time spinning until there is room again. Your present technique starves the other channels of service and wastes CPU cycles.

Also, testing isConnected() at this point is futile. It is. You connected it. That method tells you about the state of the socket, not the connection.

Try it as follows

/**
 * @param socketChannel
 * @param buf
 * @return no. of bytes written to the socket
 * @throws IOException
 */
public static int writeByteBuffer(SocketChannel socketChannel, ByteBuffer buf) throws IOException {

    boolean blocking = socketChannel.isBlocking();
    Selector selector = Selector.open();
    int totalWritten = 0;
    try {

        socketChannel.configureBlocking(false);

        // pass SelectionKey.OP_READ | SelectionKey.OP_WRITE for read and
        // write
        socketChannel.register(selector, SelectionKey.OP_WRITE);

        selector.select();

        Set<SelectionKey> selectedKeys = selector.selectedKeys();

        Iterator<SelectionKey> keyIterator = selectedKeys.iterator();

        outerOfWriting: while (keyIterator.hasNext()) {

            SelectionKey key = keyIterator.next();

            boolean writable = key.isWritable();

            if (writable) {

                SocketChannel channel = (SocketChannel) key.channel();

                boolean hasRemaining = false;
                while (hasRemaining = buf.hasRemaining()) {
                    int written = channel.write(buf);
                    totalWritten += written;

                    if (written == 0) {                         
                        selector.select();
                        selectedKeys = selector.selectedKeys();
                        keyIterator = selectedKeys.iterator();
                        continue outerOfWriting;
                    }
                }

                if (!hasRemaining) {
                    key.cancel();
                    break;
                }
            }
        }

    } finally {
        try {
            selector.close();
            socketChannel.configureBlocking(blocking);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    return totalWritten;
}

public static void main(String[] args) {

    try {
        ByteBuffer writeBuffer = ByteBuffer.allocate(8192);
        writeBuffer.clear();
        writeBuffer.put("heartbeat".getBytes());
        writeBuffer.flip();

        SocketChannel socketChannel = null;//initialize
        writeByteBuffer(socketChannel, writeBuffer);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM