通过套接字手动发送HTTP请求

Eng*_*uad 49 java sockets network-programming http http-headers

当我通过套接字发送正常的HTTP请求时,服务器不响应OK响应.我从FireFox复制了HTTP标头.这是代码:

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();
Run Code Online (Sandbox Code Playgroud)

但是,这是我收到的回复:

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>
Run Code Online (Sandbox Code Playgroud)

我知道我可以通过使用URL.openStream(),但为什么服务器在我手动发送时不识别HTTP请求?

Lyc*_*cha 48

两件事情:

  1. 您应该使用println而不是print将条目打印到单独的行.
  2. HTTP请求应以空行结束(链接).所以加pw.println("");

  • 这仅适用于Windows机器.在linux上,它只会打印LF而不是HTTP规范所需的CRLF.看到其他答案. (3认同)

Hol*_*ust 22

您不遵循HTTP RFC.

  • 标题行总是以CR LF结束(即0x0d加号0x0a).
  • 标题在第一个双换行符后结束.在您的情况下,您不包括尾随换行符,因此服务器无法识别请求标头的末尾.

通常,您应该始终尝试使用现有的HTTP库.尽管HTTP似乎是一个简单的协议(并且与其他协议进行比较),但它具有相当严格的语法和语义规则.如果您尝试自己实现,则应阅读并理解RFC 2616(及相关)的相关部分.

可悲的是,已经有太多糟糕的HTTP实现没有遵循标准,使每个人的生活变得悲惨.节省麻烦并使用您选择的语言的HTTP库.


小智 8

真正有效的正确修复,它是跨平台的:

    pw.print("GET / HTTP/1.1\r\n");
    pw.print("Host: stackoverflow.com\r\n\r\n");
Run Code Online (Sandbox Code Playgroud)

  • 我使用了“Host :”而不是“Host:”,所有的请求都收到了 Bad Request (400),花了一天时间才意识到,这真的很糟糕。 (2认同)