通过套接字手动发送HTTP请求
当我通过一个套接字发送一个正常的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请求?
两件事情:
- 您应该使用
println
而不是print
来将条目打印到单独的行中。 - HTTP请求应以空行结束( 链接 )。 所以添加
pw.println("");
你不遵循HTTP RFC 。
- 标题行总是以CR LF结尾(即
0x0d
加0x0a
)。 - 头在第一个双换行符后结束。 在你的情况,你不包括尾随的换行符,所以服务器不能识别请求头的结尾。
通常,您应该总是尝试使用现有的HTTP库。 尽pipeHTTP似乎是一个简单的协议(并且与其他协议相比),但它具有相当严格的语法和语义规则。 如果您尝试自己实现这一点,则应该阅读并理解RFC 2616(及相关)的相关部分。
可悲的是,已经有太多蹩脚的HTTP实现不遵循标准,使每个人的生活悲惨。 省去麻烦,并使用所选语言的HTTP库。
正确的解决scheme,它是真正的作品,它是跨平台:
pw.print("GET / HTTP/1.1\r\n"); pw.print("Host: stackoverflow.com\r\n\r\n");
正如前面的答案所述,下面的修复解决了这个问题。
pw.print("GET / HTTP/1.1\n\r\n"); pw.print("Host: stackoverflow.com\n\r\n");