Как распознать EOF в сокетах Java? - PullRequest
1 голос
/ 29 сентября 2011

Я хочу распознать конец потока данных в сокетах Java. Когда я запускаю приведенный ниже код, он просто зависает и продолжает работать (он зависает при значении 10).

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

String host = "example.com";
String path = "/";
Socket connection = new Socket(host, 80);

PrintWriter out = new PrintWriter(connection.getOutputStream());
  out.write("GET "+ path +" HTTP/1.1\r\nHost: "+ host +"\r\n\r\n");
out.flush();

int dataBuffer;
while ((dataBuffer = connection.getInputStream().read()) != -1)
  System.out.println(dataBuffer);

out.close();

Спасибо за любые подсказки.

Ответы [ 2 ]

6 голосов
/ 29 сентября 2011
  1. Вы должны использовать существующие библиотеки для HTTP.См. здесь .
  2. Ваш код работает должным образом.Сервер не закрывает соединение, и dataBuffer никогда не становится -1.Это происходит потому, что соединения по умолчанию поддерживаются в HTTP 1.1.Используйте HTTP 1.0 или вставьте в запрос заголовок Connection: close.

Например:

out.write("GET "+ path +" HTTP/1.1\r\nHost: "+ host +"\r\nConnection: close\r\n\r\n");
out.flush();

int dataBuffer;
while ((dataBuffer = connection.getInputStream().read()) != -1) 
   System.out.print((char)dataBuffer);

out.close();
5 голосов
/ 29 сентября 2011

На самом деле ваш код не правильный.

В HTTP 1.0 каждое соединение закрывается, и в результате клиент может определить, когда ввод закончился.

В HTTP 1.1 с постоянными соединениями базовое TCP-соединение остается открытым, поэтому клиент может определить, когда ввод заканчивается одним из следующих 2 способов:

1) HTTP-сервер помещает заголовок Content-Length, указывающий размер ответа. Это может использоваться клиентом, чтобы понять, когда ответ был полностью прочитан.

2) Ответ отправляется в Chunked-Encoding, что означает, что он приходит в чанках с префиксом размера каждого чанка. Клиент, использующий эту информацию, может создать ответ из чанков, полученных сервером.

Вы должны использовать библиотеку HTTP-клиента, поскольку реализация универсального HTTP-клиента не тривиальна (я бы даже сказал).

Чтобы быть конкретным в своем опубликованном коде, вы должны следовать одному из указанных выше подходов.

Кроме того, вы должны читать в строках, так как HTTP - это протокол, завершающийся строкой.

т.е. что-то вроде:

BufferedReader in =new BufferedReader(new InputStreamReader( Connection.getInputStream() ) );
String s=null;
while ( (s=in.readLine()) != null)  {
//Read HTTP header
     if (s.isEmpty()) break;//No more headers
   }
}

Посылая Connection: close, как предложено Хачиком, выполняет свою работу (поскольку закрытие соединения помогает определить конец ввода), но производительность ухудшается, потому что для каждого запроса вы запускаете новое соединение.

Конечно, это зависит от того, что вы пытаетесь сделать (если вам неважно)

...