52

当我通过套接字发送正常的 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();

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

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请求时服务器无法识别?

4

4 回答 4

48

两件事情:

  1. 您应该使用println而不是print将您的条目打印到单独的行中。
  2. HTTP 请求应以空行(链接)结束。所以添加pw.println("");
于 2012-05-20T13:13:31.627 回答
22

您不遵循HTTP RFC

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

通常,您应该始终尝试使用现有的 HTTP 库。尽管 HTTP 看起来是一个简单的协议(并且与其他协议相比),但它具有相当严格的句法和语义规则。如果您尝试自己实现这一点,您应该已经阅读并理解了 RFC 2616(和相关)的相关部分。

可悲的是,已经有太多糟糕的 HTTP 实现不遵循标准,这让每个人的生活都很痛苦。省去麻烦,使用您选择的语言的 HTTP 库。

于 2012-05-20T13:18:42.810 回答
12

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

    pw.print("GET / HTTP/1.1\r\n");
    pw.print("Host: stackoverflow.com\r\n\r\n");
于 2015-04-05T12:24:59.927 回答
4

如前面的答案所述,以下修复解决了该问题;

pw.print("GET / HTTP/1.1\n\r\n");
pw.print("Host: stackoverflow.com\n\r\n");
于 2015-03-24T17:11:16.293 回答