I need to write a quick and easy port forwarder. At the moment it accepts connections and can read from clients just fine, but it doesn’t get anything from the local machine it is running on. (FYI this was made to forward a webserver, because I can’t find the app I usually use to forward VS2010/2012 to the network so I made my own).
I know the exception swallowing and such is bad but that’s not important right now, I can deal with that later.
import java.io.*;
import java.net.*;
public class SocketForward {
int src = 0;
int dest = 0;
public static void main(String args[]) throws Exception {
if (args.length < 2) {
System.out.println("Usage: java SocketForward <source port> <destination port>");
System.exit(1);
} else {
new SocketForward().startRun(Integer.parseInt(args[0]), Integer.parseInt(args[1]));
}
}
public void startRun(int src, int dest) throws Exception {
try {
this.src = src;
this.dest = dest;
} catch (NumberFormatException e) {
System.out.println("Usage: java SocketForward <source port> <destination port>");
System.exit(1);
}
ServerSocket server = new ServerSocket(dest);
System.out.println("Waiting for connections...");
while (!server.isClosed()) {
new ConnHandler(src, server.accept());
}
}
}
class ConnHandler implements Runnable {
Socket clientSocket;
Socket hostSocket;
int hostport;
Thread thread;
BufferedOutputStream hostOut;
BufferedOutputStream clientOut;
BufferedInputStream hostIn;
BufferedInputStream clientIn;
public ConnHandler(int hostport, Socket clientSocket) {
System.out.println("Connected to " + clientSocket.getInetAddress());
this.clientSocket = clientSocket;
this.hostport = hostport;
this.thread = new Thread(this);
thread.start();
}
@Override
public void run() {
try {
hostSocket = new Socket("", hostport);
System.out.println("Connected to localhost:" + hostport);
hostOut = new BufferedOutputStream(hostSocket.getOutputStream());
clientOut = new BufferedOutputStream(clientSocket.getOutputStream());
hostIn = new BufferedInputStream(hostSocket.getInputStream());
clientIn = new BufferedInputStream(clientSocket.getInputStream());
new Thread() {
public void run() {
while (this == Thread.currentThread()) {
byte[] buf = new byte[8192];
try {
int len = 0;
while ((len = ConnHandler.this.clientIn.read(buf)) > 0) {
System.out.println("Client: " + new String(buf, 0, len));
ConnHandler.this.hostOut.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
break;
}
}
}
}.start();
new Thread() {
public void run() {
while (this == Thread.currentThread()) {
byte[] buf = new byte[8192];
try {
int len = 0;
while ((len = ConnHandler.this.hostIn.read(buf)) > 0) {
System.out.println("Host: " + new String(buf, 0, len));
ConnHandler.this.clientOut.write(buf, 0, len);
}
} catch (Exception e) {
e.printStackTrace();
break;
}
}
}
}.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
You are not doing any flushing, thereby introducing non-transparent man-in-the-middle behavior. This may well disturb the data flow as expected by the client and server.
A side note on code style: it is more convenient to have
try-catchoutside thewhileloop, so it breaks out automatically:Note also
Throwableinstead ofException—you’ll want to know about any error that breaks your code, not justExceptions.