Java SocketChannel читает сообщения неизвестной длины

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

    ByteBuffer buffer = ByteBuffer.allocate(1024);
    int numRead = -1;
    try {
        numRead = channel.read(buffer);
        System.out.println("numRead: " + numRead);
    }
    catch (IOException e) { e.printStackTrace();}
    if (numRead == -1) {
        this.dataMap.remove(channel);
        Socket socket = channel.socket();
        SocketAddress remoteAddr = socket.getRemoteSocketAddress();
        System.out.println("Connection closed by client: " + remoteAddr);
        channel.close();
        key.cancel();
        return;
    }
    System.out.println("Got: " + new String(buffer.array(), "windows-1251"));

Из сокета считывается 1024 байта данных. В этом случае все сообщения объединяются, и последнее сообщение не приходит полностью. Как мне прочитать данные в буфер перед разделителем сообщений '|' ? Я хочу получать каждое сообщение отдельно.


person user1221483    schedule 28.06.2012    source источник
comment
API сокетов сделает это за вас. Так как он уже находится в буфере.   -  person Woot4Moo    schedule 28.06.2012
comment
вот хорошо читается. github.com/robbiehanson/CocoaAsyncSocket/wiki/CommonPitfalls рассказывает о том, о чем вы спрашиваете. библиотека предназначена для obj-c, но статья посвящена распространенным ловушкам с tcp/udp, поэтому она применима   -  person owen gerig    schedule 28.06.2012


Ответы (2)


Зависит от протокола, но если протокол основан на символе-разделителе сообщения, ваш единственный вариант — прочитать как можно больше без блокировки, а затем просмотреть прочитанное содержимое, чтобы найти разделитель. Вам нужно делать это в цикле, пока соединение не будет закрыто (или пока ваша сторона не решит закрыть соединение).

Конечно, вы можете читать сразу несколько сообщений и даже часть сообщений, поэтому вам нужно убедиться, что вы правильно обрабатываете такие случаи.

person biziclop    schedule 28.06.2012
comment
К сожалению, этот способ мне не подходит - person user1221483; 28.06.2012
comment
Это позор, потому что нет другого пути, который бы существенно отличался. Если бы протокол был другим, например, если бы каждое сообщение начиналось с заголовка фиксированного размера, содержащего длину сообщения, он был бы. - person biziclop; 28.06.2012

В TCP нет такого понятия, как сообщение. Это API потока байтов. Если вам нужны сообщения, вы должны реализовать их самостоятельно, используя разделитель, пару STX/ETX, префикс длины слова, протокол с самоописанием и т. д.

person user207421    schedule 28.06.2012