SocketChannel.write()编写问题

时间:2011-05-06 03:24:47

标签: java nio

这里的问题是我可以看到数据正被写入套接字,但它并不总是被发送。

这是一个代码片段

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);
    }
}

我使用TCPMon来查看实际数据是否写入套接字 - 它的作用是什么。

但是使用WireShark(另一种网络监控工具)我看不到数据包通过网卡。

任何帮助将不胜感激

2 个答案:

答案 0 :(得分:5)

无论如何你的代码都是错误的。如果写入返回零,则套接字发送缓冲区已满,因此您应该注册OP_WRITE并返回到选择循环,而不是浪费时间旋转直到再次有空间。您现有的技术使其他服务渠道匮乏,浪费CPU周期。

此外,此时测试isConnected()是徒劳的。它是。你连接了它。该方法告诉您套接字的状态,而不是连接。

答案 1 :(得分:-1)

尝试如下

/**
 * @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();
    }
}