Вопрос по java, http-headers, sockets, network-programming, http – Отправить HTTP-запрос вручную через сокет

41

Когда я отправляю обычный 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-запрос, когда я отправляю его вручную?

Я думаю, что вы должны отправить дополнительный символ новой строки после всех ваших заголовков;pw.println();и использоватьprintln() для заголовков, а? Torious
И новые строки должны иметь форму \ r \ n для HTTP. user207421
@ Правда, вот в чем проблема. Спасибо :) Eng.Fouad
Что ж, когда я пытаюсь проверить ваш код, он ничего не печатает. user6538026

Ваш Ответ

4   ответа
4

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

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

HTTP RFC.

Header lines are always ended by a CR LF (i.e. 0x0d plus 0x0a). The header ends after the first double-newline. In your case, you don't include the trailing newline so the server doesn't recognize the end of the request headers.

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

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

8

которое действительно работает и является кроссплатформенным:

    pw.print("GET / HTTP/1.1\r\n");
    pw.print("Host: stackoverflow.com\r\n\r\n");
я использовалHost :  вместоHost:  и все получили Bad Request (400), и потребовался день, чтобы понять, что это действительно отстой.
43

You should use println instead of print to print your entries to separate lines. HTTP request should end in a blank line (link). So add pw.println("");
Это работает только на машинах Windows. В Linux он будет печатать только LF вместо CRLF, который необходим для спецификации HTTP. Смотрите другие ответы.
Отлично. Добавление пустой строки важно!
почему это дает иHTTP/1.1 400 Bad Request когда я сменил хозяина наpw.println("Host: httpstackoverflow.com/questions/10673684/send-http-request-manually-via-socket");

Похожие вопросы