метод чтения и записи для больших данных в сокетах не работает надежно - PullRequest
1 голос
/ 23 апреля 2009

Я создал сокет для программирования взаимодействия с сервером. Я читаю данные, используя read(byte[]) из DataInputStream, а также записываю данные, используя write(byte[]) из DataOutputStream.

Когда я отправляю небольшое количество данных, моя программа работает нормально. Но если я отправляю данные размером 20000 символов и отправляю их 10 раз, тогда я могу получить данные 8 раз идеально, но не 2 раза.

Так можно ли надежно отправлять и получать данные, используя чтение и запись при программировании сокетов?

Ответы [ 3 ]

8 голосов
/ 23 апреля 2009

Я предполагаю, что вы отправляете один вызов read() и предполагаете, что он вернет все запрашиваемые вами данные. Потоки обычно не работают таким образом. Он будет блокироваться до тех пор, пока некоторые данные не будут доступны, но он не будет ждать, пока у него не будет достаточно данных для заполнения массива.

Обычно это означает циклический цикл. Например:

byte[] data = new byte[expectedSize];
int totalRead = 0;
while (totalRead < expectedSize)
{
    int read = stream.read(data, totalRead, expectedSize-totalRead);
    if (read == -1)
    {
        throw new IOException("Not enough data in stream");
    }
    totalRead += read;
}

Если вы не знаете, сколько байтов вы ожидаете, во-первых, вы, возможно, захотите все еще выполнить цикл, но на этот раз, пока read() не вернет -1. Используйте буфер (например, 8 КБ) для чтения и записи в ByteArrayOutputStream. Когда вы закончите чтение, вы можете получить данные из ByteArrayOutputStream в виде байтового массива.

1 голос
/ 23 апреля 2009

Абсолютно - TCP Sockets - это надежный сетевой протокол при условии правильного использования API.

Вам действительно нужно проверять количество байтов, которые вы получаете при каждом вызове read ().

Сокеты произвольно решат, что у вас достаточно данных, и передадут их обратно при вызове чтения - количество может зависеть от многих факторов (размер буфера, доступность памяти, время восстановления сети и т. Д.), Большинство из которых непредсказуемы. Для небольших буферов вы обычно получаете столько байтов, сколько вы просили, но для больших размеров буфера read () часто возвращает меньше данных, чем вы просили - вам нужно проверить количество прочитанных байтов и повторить вызов read для остальные байты.

Также возможно, что что-то в вашей сетевой инфраструктуре (маршрутизатор, брандмауэр и т. Д.) Неправильно сконфигурировано и перегружает большие пакеты.

0 голосов
/ 23 апреля 2009

Ваша проблема в том, что в потоке сервера вы должны вызывать outputtream.flush (), чтобы указать, что буферизованные данные должны отправляться на другой конец сообщения

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...