Чтение того, что доступно с Socket без блокировки

Я работаю на сервере, который считывает данные, отправленные клиентом, но размер не известен, и я не могу изменить клиент для отправки размера.

Я хочу прочитать данные от клиента, пока он не блокирует и не ждет ответа сервера. Я пытался использовать available(), он работает иногда, но иногда он просто возвращает ноль, даже когда в потоке есть некоторые данные.

while((len = in.available()) != 0)
    in.read(b,0,len);

Есть ли способ сделать это в Java? Я знаю асинхронные методы, но никогда не пробовал это, поэтому, если кто-то может предоставить короткий пример.

Ответ 1

Использование available() - единственный способ сделать это, не прибегая к асинхронным методам.

Вам не нужно полагаться на значение, возвращаемое available(); просто убедитесь, что есть "некоторые" данные, чтобы убедиться, что read не будет блокироваться. Однако вы должны проверить значение, возвращаемое read (фактическое количество байтов, считанных в массиве):

// Process all data currently available
while (in.available() != 0)
{
    int nb = in.read(b);
    // Process nb bytes
}

Обратите внимание, что available возврат 0 не означает, что конец данных был достигнут - это просто означает, что нет данных для немедленного потребления (данные могут стать доступными в следующем миллисекунде). Таким образом, вам понадобится другой механизм, чтобы сервер знал, что клиент больше не будет отправлять данные и ожидает ответа.

Ответ 2

InputStream JavaDocs для метода available() четко заявляет, что

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

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

Ответ 3

Я перепробовал много решений, но нашел только одно, которое не блокировало выполнение:

BufferedReader inStream = new BufferedReader(new InputStreamReader(yourInputStream));
String line;
while(inStream.ready() && (line = inStream.readLine()) != null) {
    System.out.println(line);
}