SocketChannel.write () проблема записи - PullRequest
4 голосов
/ 06 мая 2011

Проблема здесь в том, что я вижу, что данные записываются в сокет, но они не ВСЕГДА отправляются.

Вот фрагмент кода

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 (другого инструмента мониторинга сети) я не вижу, как пакет проходит через NIC.

Буду признателен за любую помощь

Ответы [ 2 ]

5 голосов
/ 10 мая 2011

Ваш код в любом случае неверен.Если запись возвращает ноль, буфер отправки сокета заполнен, поэтому вы должны зарегистрировать OP_WRITE и вернуться к циклу выбора, а не тратить время на вращение, пока не освободится место.Ваша нынешняя техника лишает других каналов обслуживания и тратит впустую циклы ЦП.

Кроме того, тестирование isConnected() на этом этапе бесполезно.Это.Вы подключили это.Этот метод сообщает вам о состоянии сокета, а не о соединении.

0 голосов
/ 23 февраля 2016

Попробуйте следующим образом

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