Greetings,
I am having trouble writing a simple http proxy server. The proxy works quite well, except for a java.net.SocketException (broken pipe) that emerges quite randomly, especially when the traffic is heavier. What could be causing this? I have met lots of cases where firewalls and NAT issues were involved, but for me this is not the case.
I wonder if this has anything to do with the headers in the request the browser sends to the proxy, since I had to change the network.http.proxy.keep-alive (I set it to false) preference of the browser (firefox) to avoid non-closing connections. Is there possibly another preference that has such an impact on my proxy?
The proxy code follows.
package proxy;
import java.net.*;
import java.util.*;
import java.io.*;
public class Proxy implements Runnable {
private int port;
public Proxy(int port) {
this.port = port;
}
public void run() {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(0);
ExecutorService threadExecutor = Executors.newFixedThreadPool(200);
while (true) {
threadExecutor.execute(new ConnectionHandler(serverSocket.accept()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
int port = 66666;
Proxy me = new Proxy(port);
me.run();
}
}
class ConnectionHandler implements Runnable {
private Socket peerSocket;
public ConnectionHandler(Socket peerSocket) throws SocketException {
this.peerSocket = peerSocket;
}
public void run() {
HttpRequest request; /* utility class for the http request, not important */
Socket remoteSocket;
try {
byte[] req = new byte[10240];
int bytesRead;
InputStream peerIn = peerSocket.getInputStream();
bytesRead = peerIn.read(req);
request = new HttpRequest(new String(req, 0, bytesRead));
URL url = request.getRequestUrl(); /*returns the remote host's url from the request */
int port = url.getPort();
if (port == -1) {
port = 80;
}
remoteSocket = new Socket(url.getHost(), port);
OutputStream out = remoteSocket.getOutputStream();
InputStream in = remoteSocket.getInputStream();
//write request to remote host's socket
out.write(request.getRequest().getBytes());
out.flush();
OutputStream peerOut = peerSocket.getOutputStream();
int bytes;
byte response[] = new byte[32768];
while ((bytes = in.read(response)) > 0) {
peerOut.write(response, 0, bytes); /* The exception is thrown here */
peerOut.flush();
}
out.close();
in.close();
peerOut.close();
peerSocket.close();
remoteSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
The exception's stack trace is
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at proxy.ConnectionHandler.run(ConnectionHandler.java:72) /* This line is marked above */
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)