Подтвердить что ты не робот

Отправить HTTP-запрос вручную через сокет

Когда я отправляю обычный HTTP-запрос через сокет, сервер не отвечает с ответом OK. Я скопировал HTTP-заголовок из FireFox. Вот код:

Socket s = new Socket(InetAddress.getByName("stackoverflow.com"), 80);
PrintWriter pw = new PrintWriter(s.getOutputStream());
pw.print("GET / HTTP/1.1");
pw.print("Host: stackoverflow.com");
pw.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
String t;
while((t = br.readLine()) != null) System.out.println(t);
br.close();

Однако вот ответ, который я получил:

HTTP/1.0 408 Request Time-out
Cache-Control: no-cache
Connection: close
Content-Type: text/html

<html><body><h1>408 Request Time-out</h1>
Your browser didn't send a complete request in time.
</body></html>

Я знаю, что могу сделать это, используя URL.openStream(), но почему сервер не идентифицирует HTTP-запрос при отправке вручную?

4b9b3361

Ответ 1

Две вещи:

  • Вы должны использовать println вместо print для печати ваших записей для разделения строк.
  • HTTP-запрос должен заканчиваться пустой строкой (ссылка). Поэтому добавьте pw.println("");

Ответ 2

Вы не следуете HTTP RFC.

  • Линии заголовка всегда заканчиваются CR LF (т.е. 0x0d плюс 0x0a).
  • Заголовок заканчивается после первой двойной строки. В вашем случае вы не включаете конечную новую строку, чтобы сервер не распознал конец заголовков запросов.

Как правило, вы всегда должны пытаться использовать существующие библиотеки HTTP. Хотя HTTP, кажется, простой протокол (и он сравнивается с другими), он имеет довольно строгие синтаксические и семантические правила. Если вы попытаетесь реализовать это самостоятельно, вы должны прочитать и понять соответствующие части RFC 2616 (и связанные с ними).

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

Ответ 3

Правильное исправление, которое действительно работает, и это кросс-платформа:

    pw.print("GET / HTTP/1.1\r\n");
    pw.print("Host: stackoverflow.com\r\n\r\n");

Ответ 4

Следующее исправление, упомянутое в предыдущих ответах, решает проблему;

pw.print("GET / HTTP/1.1\n\r\n");
pw.print("Host: stackoverflow.com\n\r\n");