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

时间:2012-05-20 13:08:12

标签: java http sockets network-programming 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();

然而,这是我收到的回复:

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 个答案:

答案 0 :(得分:44)

两件事:

  1. 您应该使用println代替print将条目打印为单独的行。
  2. HTTP请求应以空行结束(link)。所以添加pw.println("");

答案 1 :(得分:22)

您没有关注HTTP RFC

  • 标题行始终以CR LF结尾(即0x0d0x0a)。
  • 标题在第一个双换行符后结束。在您的情况下,您不包括尾随换行符,因此服务器无法识别请求标题的结尾。

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

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

答案 2 :(得分:8)

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

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

答案 3 :(得分:4)

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

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