При чтении больших данных в Java Socket возникает периодическая ошибка - PullRequest
0 голосов
/ 07 декабря 2010

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

Я провел некоторое исследование в Интернете и следовал примерам программирования сокетов, которые нашел, но все ещеЯ не мог решить проблему.Ниже моя текущая реализация.

     BufferedInputStream is = new BufferedInputStream(socket.getInputStream());

    //I know the size of data that I am expecting from the server
    byte[] buffer = new byte[length];

    int count = 0;
    int current = 0;

    while(count < length) {
        current = is.read(buffer, count, length - count);

        if(current == -1) {
            break;
        } else {                
            count += current;
        }          
    }

Я знаю размер данных, которые я ожидаю от сервера.Когда возникает проблема, метод read () возвращает -1, прежде чем данные будут полностью получены с сервера.У меня нет доступа к реализации на стороне сервера.Пожалуйста, сообщите мне, если я что-то упустил в своем коде или есть ли лучший способ сделать это.

Ответы [ 3 ]

3 голосов
/ 07 декабря 2010

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

Возможно, сервер неправильно закодирован, например закрывает сокет вместо внешнего выходного потока, что приводит к потере данных.Или, возможно, ваш конец неверен, например, путем создания нескольких BufferedInputStreams для одного сокета вместо одного для срока службы сокета.

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

1 голос
/ 07 декабря 2010

Ваш код выглядит в основном здоровым.(Использование BufferedInputStream не улучшает производительность в этом случае. Во всяком случае, это делает его медленнее. Однако это вряд ли вызовет эту проблему.)

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

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

0 голосов
/ 07 декабря 2010

В вашем коде есть серьезные проблемы:

Предполагая длину = 8 ГБ

Вы получите много проблем при создании байта [] такого размера.

int count
int current

это должно быть

long count
long current

но если вы сделаете это, код больше не будет компилироваться. Таким образом, у вас есть Максимальный размер файла Integer.MAX_VALUE. если вы храните вашу загрузку в bytearray. (Спасибо EJP)

Вы должны записать эти данные в файл или другую память, кроме ОЗУ. С 32-битной JVM вы никогда не создадите байт [] больше, чем ~ 1,3 ГБ.

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