我正在尝试使用套接字在java中编写一个简单的HTTP代理,基本上只是接受一个请求,读取它并将其转发到服务器,读取响应并返回给浏览器。我遇到的问题是在响应中有一个我解析的 Content-Length 字段,我编写了一个循环来准确读取要发送回浏览器的字节数,但它在之前到达流的末尾读取正确的数量(读取返回 -1)。我将在下面添加我的代理的基本代码 - 主线程只是在建立连接时生成这些类之一。有没有人有任何想法?这将非常有帮助。
public class ProxyClient implements Runnable {
Socket clientSocket;
Socket netflixSocket;
InputStream isClient = null;
OutputStream osClient = null;
BufferedReader brClient = null;
InputStream isNetflix = null;
OutputStream osNetflix = null;
BufferedReader brNetflix = null;
boolean connectedNetflix = false;
String meta = ""; //header data
public ProxyClient(Socket connectionSocket){
this.clientSocket = connectionSocket;
try {
isClient = clientSocket.getInputStream();
osClient = clientSocket.getOutputStream();
brClient = new BufferedReader(new InputStreamReader(isClient));
} catch (IOException e1) {
e1.printStackTrace();
}
}
@Override
public void run() {
String host = "";
String temp; // temp read line from buffer
String getRequest;
int contentLength; //holder for reading bytes.
int bytesRead; // Total number of bytes read during consecutive reads
int numRead; // Number of bytes read in a single read.
byte[] dataBuffer = new byte[2000000];
while(true){
try {
// reading client HTTP request / connecting
host = "";
meta = "";
contentLength = 0;
getRequest = "";
while((temp = brClient.readLine()).length() > 0){
meta += temp + "\r\n";
//connect to server
if(!connectedNetflix && temp.startsWith("Host")){
// extract the host to connect to
host = temp.substring(temp.indexOf(':') + 2);
//connect to the host
try {
netflixSocket = new Socket(host, 80);
osNetflix = netflixSocket.getOutputStream();
isNetflix = netflixSocket.getInputStream();
brNetflix = new BufferedReader(new InputStreamReader(isNetflix));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
connectedNetflix = true;
}
else if (temp.startsWith("Content-Length:")) {
contentLength = Integer.parseInt(temp.substring(temp.indexOf(':') + 2));
}
}
meta += "\r\n"; // add blank line
//read request content, if any
if(contentLength > 0){
numRead = 0;
bytesRead = 0;
while(bytesRead != contentLength){
numRead = isNetflix.read(dataBuffer, bytesRead, contentLength-bytesRead);
if(numRead >0){
bytesRead += numRead;
}
}
}
//send to server
osNetflix.write(meta.getBytes());
if(contentLength > 0){
osClient.write(dataBuffer, 0, contentLength);
}
osNetflix.flush();
//Read response from server
contentLength = 0;
meta = "";
while((temp = brNetflix.readLine()).length() > 0){
meta += temp + "\r\n";
if (temp.startsWith("Content-Length:")) {
contentLength = Integer.parseInt(temp.substring(temp.indexOf(':') + 2));
}
}
meta += "\r\n"; // add blank line
//read Netflix content
if(contentLength > 0){
numRead = 0;
bytesRead = 0;
while(bytesRead != contentLength){
numRead = isNetflix.read(dataBuffer, bytesRead, contentLength-bytesRead);
if(numRead >0){
bytesRead += numRead;
}
}
}
// write back to browser/client
osClient.write(meta.getBytes());
if(contentLength > 0){
osClient.write(dataBuffer, 0, contentLength);
}
osClient.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这是一个示例响应标头:
HTTP/1.1 200 OK
Server: Apache
Accept-Ranges: bytes
Content-Type: text/plain
Content-Type: application/octet-stream
Access-Control-Allow-Origin: *
Content-Type: application/octet-stream
Last-Modified: Fri, 17 Jun 2011 07:52:37 GMT
ETag: "0d6a07a1c0e6772459e73f7c0c4fd899:1308297157"
Date: Thu, 31 May 2012 01:54:10 GMT
Content-Length: 294183
Connection: close
Cache-Control: no-store