我正在尝试在java中编写一个简单的Web代理,它接受GET和POST请求。我写了以下代码:
import java.net.*;
import java.io.*;
import java.nio.CharBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
public class InterceptionProxy2 {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = null;
boolean listening = true;
int port = 1234;
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
System.out.println("Port Error");
System.exit(-1);
}
while (listening) {
new ProxyThread2(serverSocket.accept()).start();
}
serverSocket.close();
}
}
class ProxyThread2 extends Thread {
private Socket clientSocket = null;
private Socket serverSocket = null;
public ProxyThread2(Socket socket) {
super("ProxyThread2");
this.clientSocket = socket;
}
public void run() {
//Stream to put data to the browser
PrintWriter outGoing = null;
try {
outGoing = new PrintWriter(clientSocket.getOutputStream(), true);
//Stream to get data from the browser
BufferedReader inComing = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String incomingRequest;
String url = "";
String request = "";
String response = "";
//Take the incoming request
char[] buf = new char[8196]; //8196 is the default max size for GET requests in Apache
int bytesRead = inComing.read(buf); //BytesRead need to be calculated if the char buffer contains too many values
request = new String(buf, 0, bytesRead);
System.out.println("Request");
System.out.println(request);
//Create a new socket for connecting to destination server
serverSocket = new Socket("localhost", 80);
PrintWriter pOut = new PrintWriter(serverSocket.getOutputStream(), true);
//Reader for response from destination server
BufferedReader pIn = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
//Put data into the new socket(to the apache server) and receive its output
pOut.print(request);
pOut.flush();
bytesRead = pIn.read(buf);
//Check if data is read
if (bytesRead > 0) {
response = new String(buf, 0, bytesRead);
}
System.out.println("Response");
System.out.println(response);
//Put data back into the original client socket
outGoing.write(response);
} catch (IOException ex) {
Logger.getLogger(ProxyThread2.class.getName()).log(Level.SEVERE, null, ex);
} finally {
outGoing.close();
}
}
}
系统正确地将请求和响应打印为输出,但是,代理不会将回复提供给浏览器。 outGoing流定义有什么问题吗?或者我应该创建一个新的套接字来将数据发送回浏览器吗?
答案 0 :(得分:8)
您无需创建java.net.ServerSocket
的其他实例。因为您必须连接到端口80
,所以您是客户端。
Socket socket = new Socket("localhost", 80);
e.g:
class ProxyThread extends Thread {
private final Socket clientSocket;
public ProxyThread(Socket socket) {
this.clientSocket = socket;
}
public void run() {
try {
// Read request
InputStream incommingIS = clientSocket.getInputStream();
byte[] b = new byte[8196];
int len = incommingIS.read(b);
if (len > 0) {
System.out.println("REQUEST"
+ System.getProperty("line.separator") + "-------");
System.out.println(new String(b, 0, len));
// Write request
Socket socket = new Socket("localhost", 80);
OutputStream outgoingOS = socket.getOutputStream();
outgoingOS.write(b, 0, len);
// Copy response
OutputStream incommingOS = clientSocket.getOutputStream();
InputStream outgoingIS = socket.getInputStream();
for (int length; (length = outgoingIS.read(b)) != -1;) {
incommingOS.write(b, 0, length);
}
incommingOS.close();
outgoingIS.close();
outgoingOS.close();
incommingIS.close();
socket.close();
} else {
incommingIS.close();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
答案 1 :(得分:1)
您的代码适用于简单的文本文件或HTML。 只有一个问题,只有HTTP头是文本数据,HTTP消息正文中的所有内容都可以是简单的字节数据,如图像。
您不应使用PrintWriter和/或字符串来转换响应。 您应该简单地转发从服务器获得的字节缓冲区。 只有在你想要自己显示HTTP消息时才转换字节缓冲区。