我正在尝试使用java开发代理服务器。 我按照以下步骤操作:
以下代码适用于来自浏览器的http请求,但不适用于https请求。当浏览器点击https url时,代理从目标服务器获取响应但无法发送回浏览器。它给出了
Encountered exception: java.net.SocketException: Connection reset by peer: socket write error
代码:
import java.net.*;
import java.io.*;
import java.security.Security;
import java.util.*;
import javax.net.ssl.HttpsURLConnection;
public class ProxyThread extends Thread {
private Socket socket = null;
private static final int BUFFER_SIZE = 32768;
List<RequestProperty> properties;
DataOutputStream out;
BufferedReader in;
String urlToCall;
public ProxyThread(Socket socket) {
super("ProxyThread");
this.socket = socket;
}
@Override
public void run() {
try {
out = new DataOutputStream(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
properties = new ArrayList<>();
String inputLine;
int cnt = 0;
String method = "";
while ((inputLine = in.readLine()) != null) {
if (inputLine.equals("")) {
break;
}
System.out.println(inputLine);
//parse the first line of the request to find the url
if (cnt == 0) {
String[] tokens = inputLine.split(" ");
method = tokens[0];
urlToCall = tokens[1];
System.out.println("Request for : " + urlToCall);
}
if (cnt > 0) {
String[] tokens = inputLine.split(" ");
String key = tokens[0].replace(":", "");
String value = "";
for (int i = 1; i < tokens.length; i++) {
value = value + tokens[i];
}
properties.add(new RequestProperty(key, value));
}
cnt++;
}
//end get request from client
if (method.equalsIgnoreCase("connect")) {
serveConnect();
} else {
serveGet();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void serveGet() {
HttpURLConnection conn;
try {
out = new DataOutputStream(socket.getOutputStream());
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Request read from clien :::::::\n\n\n\n");
BufferedReader rd = null;
try {
//begin send request to server, get response from server
URL url = new URL(urlToCall);
conn = (HttpURLConnection) url.openConnection();
for (RequestProperty property : properties) {
conn.setRequestProperty(property.getKey(), property.getValue());
}
conn.setDoInput(true);
// doing HTTP posts
conn.setDoOutput(true);
// Get the response
InputStream is = null;
try {
is = conn.getInputStream();
rd = new BufferedReader(new InputStreamReader(is));
} catch (IOException ioe) {
System.out.println(
"********* IO EXCEPTION **********: " + ioe);
}
//end send request to server, get response from server
System.out.println("RESPOSE TO CLIENT ::::::::::");
//begin send response to client
byte by[] = new byte[BUFFER_SIZE];
int index = is.read(by, 0, BUFFER_SIZE);
while (index != -1) {
System.out.println(new String(by));
out.write(by, 0, index);
index = is.read(by, 0, BUFFER_SIZE);
}
out.flush();
//end send response to client
} catch (Exception e) {
//can redirect this to error log
System.err.println("Encountered exception: " + e);
out.writeBytes("");
}
//close out all resources
if (rd != null) {
rd.close();
}
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void serveConnect() {
System.out.println("Connect method called. ");
URLConnection conn;
try {
System.setProperty("java.protocol.handler.pkgs",
"com.sun.net.ssl.internal.www.protocol");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
String url = "https://" + urlToCall;
out = new DataOutputStream(socket.getOutputStream());
URL url2 = new URL(url);
URLConnection con = url2.openConnection();
for (RequestProperty property : properties) {
if (!property.getKey().equalsIgnoreCase("CONNECT")) {
con.setRequestProperty(property.getKey(), property.getValue());
}
}
InputStream inputStream = con.getInputStream();
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
out.write(line.getBytes());
out.flush();
}
} catch (Exception e) {
System.err.println("Encountered exception: " + e);
}
}
}