Сокет Java, возвращающий неполный ByteBuffer - PullRequest
1 голос
/ 27 апреля 2010

У меня есть socketChannel, настроенный как блокирующий, но при чтении из этого сокета байтовых буферов размером 5 Кб иногда я получаю неполный буфер.

    ByteBuffer messageBody = ByteBuffer.allocate(5*1024);
    messageBody.mark();
    messageBody.order(ByteOrder.BIG_ENDIAN);
    int msgByteCount = channel.read(messageBody);

В некоторых случаях messageBody не полностью заполнен, и channel.read () не возвращает -1 или исключение, но фактическое количество прочитанных байтов (которое меньше 5 КБ).

Кто-нибудь сталкивался с подобной проблемой?

Ответы [ 3 ]

4 голосов
/ 27 апреля 2010

Вот так читает работа. Документация SocketChannel гласит:

Операция чтения может не заполнить буфер, и фактически она может вообще не читать никаких байтов. [...] Однако гарантируется, что если канал находится в режиме блокировки и в буфере остается хотя бы один байт, то этот метод будет блокировать , пока не будет прочитан хотя бы один байт [выделение добавлено].

1 голос
/ 27 апреля 2010

Когда вы используете сокеты, вы должны ожидать, что сокет может передавать меньше байтов, чем вы ожидаете. Вы должны зациклить метод .read, чтобы получить остаток байтов.

Это также верно, когда вы отправляете байты через сокет. Вы должны проверить, сколько байтов было отправлено, и выполнить цикл отправки, пока все байты не будут отправлены.

Это происходит из-за того, что сетевые уровни разделяют сообщения на несколько пакетов. Если ваши сообщения короткие, то вы вряд ли столкнетесь с этим. Но вы всегда должны кодировать это.

При 5 Кбайт на буфер вы, скорее всего, увидите, что сообщение отправителя разбито на несколько пакетов. Каждая операция чтения получит один пакет, который является только частью вашего сообщения.

0 голосов
/ 27 апреля 2010

TCP / IP отправляет информацию в пакетах, они не всегда доступны во время чтения, поэтому вы должны выполнять чтение в цикле.

           char [] buffer = new char[1024];
           int chars_read;
           try
           {
              while((chars_read = from_server.read(buffer)) != -1)
              {
                 to_user.write(buffer,0,chars_read);
                 to_user.flush();
              }
           }
           catch(IOException e)
           {
              to_user.println(e);
           }

Посмотреть это сообщение

...