所以我正在创建一个抓取HTTP请求的Web代理,确保GET / POST / HEAD大写,并修复第一行中的路径:
-------------------
------REQUEST------
-------------------
GET http://boundlessecho.com/story.html HTTP/1.1
Host: boundlessecho.com
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Port 80 Connected
-------------------
---FIXED REQUEST---
-------------------
GET /story.html HTTP/1.1
Host: boundlessecho.com
Proxy-Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
然后将此数据发送到DNS请求之后指定的服务器,该请求获取主机名和端口号(100次中的99次,未指定端口,因此它将转到端口80,这是默认的HTTP端口)。
之后,我将HTTP响应从服务器发送回客户端/浏览器;但是,很多时候,它会在接收HTTP响应部分时被捕获。
BufferedReader feedback = new BufferedReader(new InputStreamReader(requestedServer.getInputStream()));
BufferedWriter showData = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"));
String line;
String header = "";
while (!(line = feedback.readLine()).equals("")) {
header += line + "\n";
}
int length = getLengthOfData(header);
showData.write(header, 0, header.length());
showData.write("\n", 0, 1);
showData.flush();
DataInputStream getBodyData = new DataInputStream(requestedServer.getInputStream());
DataOutputStream sendBodyData = new DataOutputStream(clientSocket.getOutputStream());
if (length != -1) {
byte[] b = new byte[length];
getBodyData.read(b, 0, length);
sendBodyData.write(b, 0, length);
sendBodyData.flush();
}
sendData.close();
showData.close();
feedback.close();
sendBodyData.close();
getBodyData.close();
查找内容长度的方法:
// Simply returns the Content-Length as an integer
public int getLengthOfData(String header) {
if (header.indexOf("Content-Length:") == -1) {
return -1;
}
return Integer.parseInt(header.substring(header.indexOf("Content-Length:") + 16, header.indexOf("\n", header.indexOf("Content-Length:"))));
}
有谁知道为什么它会卡在feedback.readLine()上,或者我的代码中的其他地方是否存在导致此问题的问题?
注意:它只会卡在某些请求上。有些请求有效!
注2:代码从原始帖子更新。
注3:代码再次更新。
答案 0 :(得分:2)
您对回复的阅读不完整。您需要首先阅读响应标头(读取直到您到达表示标头末尾的CRLF CRLF
对),然后您需要分析标头以了解是否以及如何读取任何其他数据。 HEAD
个回复以及所有1xx
,204
和304
回复都没有正文内容,因此请勿尝试为其阅读正文。其他任何东西都有一个正文,其长度取决于Transfer-Encoding
,Content-Length
和Context-Type
响应标头的特定值,因此您需要查看它们并采取相应的行动。< / p>
阅读RFC 2616 Section 4.4 "Message Length"了解更多详情以及您必须遵循的确切规则。
基本上,您必须实现以下逻辑:
Read and parse HTTP headers
if not successful:
throw error
if response can contain message body:
if HTTP version is 1.1+ and Transfer-encoding is not identity:
while true:
read line, extract delimited ASCII hexadecimal, the chunk size
if not successful:
throw error
if chunk size is 0:
break while loop
read chunk size number of bytes
read and parse trailing HTTP headers
else if Content-Length is specified:
read Content-Length number of bytes
else if Content-Type is "multipart/byteranges":
read and parse MIME-encoded chunks until terminating MIME boundary is reached
else:
read until connection is closed