简体   繁体   English

SocketChannel.write()编写问题

[英]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. 我使用TCPMon来查看实际数据是否被写入套接字 - 它是做什么的。

But using WireShark (another network monitoring tool) I cannot see the packet going through the NIC. 但是使用WireShark(另一种网络监控工具)我看不到数据包通过网卡。

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. 如果写入返回零,则套接字发送缓冲区已满,因此您应该注册OP_WRITE并返回到选择循环,而不是浪费时间旋转直到再次有空间。 Your present technique starves the other channels of service and wastes CPU cycles. 您现有的技术使其他服务渠道匮乏,浪费CPU周期。

Also, testing isConnected() at this point is futile. 此外,此时测试isConnected()是徒劳的。 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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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