I need a Java Proxy Server that let me connect to [localhost:9318] through [localhost:9418], like:
[my browser] -> [localhost:9418] -> [localhost:9318]
for that I tried this code:
http://www.java2s.com/Code/Java/Network-Protocol/Asimpleproxyserver.htm
package com.example.proxyserver;
import java.io.*;
import java.net.*;
public class App {
public static void main(String[] args) throws IOException {
try {
String host = "localhost";
int remoteport = 9318;
int localport = 9418;
// Print a start-up message
System.out.println("Starting proxy for " + host + ":" + remoteport + " on port " + localport);
// And start running the server
runServer(host, remoteport, localport); // never returns
} catch (Exception e) {
System.err.println(e);
}
}
/**
* runs a single-threaded proxy server on the specified local port. It never
* returns.
*/
public static void runServer(String host, int remoteport, int localport) throws IOException {
// Create a ServerSocket to listen for connections with
ServerSocket ss = new ServerSocket(localport);
final byte[] request = new byte[1024];
byte[] reply = new byte[4096];
while (true) {
Socket client = null, server = null;
try {
// Wait for a connection on the local port
client = ss.accept();
final InputStream streamFromClient = client.getInputStream();
final OutputStream streamToClient = client.getOutputStream();
// Make a connection to the real server.
// If we cannot connect to the server, send an error to the
// client, disconnect, and continue waiting for connections.
try {
server = new Socket(host, remoteport);
} catch (IOException e) {
PrintWriter out = new PrintWriter(streamToClient);
out.print("Proxy server cannot connect to " + host + ":" + remoteport + ":\n" + e + "\n");
out.flush();
client.close();
continue;
}
// Get server streams.
final InputStream streamFromServer = server.getInputStream();
final OutputStream streamToServer = server.getOutputStream();
// a thread to read the client's requests and pass them
// to the server. A separate thread for asynchronous.
Thread t = new Thread() {
public void run() {
int bytesRead;
try {
while ((bytesRead = streamFromClient.read(request)) != -1) {
streamToServer.write(request, 0, bytesRead);
streamToServer.flush();
}
} catch (IOException e) {
}
// the client closed the connection to us, so close our
// connection to the server.
try {
streamToServer.close();
} catch (IOException e) {
}
}
};
// Start the client-to-server request thread running
t.start();
// Read the server's responses
// and pass them back to the client.
int bytesRead;
try {
while ((bytesRead = streamFromServer.read(reply)) != -1) {
streamToClient.write(reply, 0, bytesRead);
streamToClient.flush();
}
} catch (IOException e) {
}
// The server closed its connection to us, so we close our
// connection to our client.
streamToClient.close();
} catch (IOException e) {
System.err.println(e);
} finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
}
catch (IOException e) {
}
}
}
}
}
This code works but it is very slow.
Do you know what do I need to do in order to increase the speed?
Or maybe do you know about another Java Proxy Server code that be fast?
Thanks!
Related
I have some simple client and server code, where the client sends some bytes to the server, and the server responds with some bytes. The client prints the received bytes, and then closes the socket.
This works fine the first time the client runs, but subsequent calls get no response.
package sockets.com;
// Client Side
import java.io.*;
import java.net.*;
public class ClientSideTCPSocket {
public void run() {
try {
int serverPort = 4023;
InetAddress host = InetAddress.getByName("localhost");
System.out.println("Connecting to server on port " + serverPort);
Socket socket = new Socket(host, serverPort);
System.out.println("Just connected to " + socket.getRemoteSocketAddress());
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
String s = "HELLO SERVER";
byte[] bytes = s.getBytes("US-ASCII");
for (byte b : bytes) {
out.write(b);
}
int ch = 0;
while ((ch = in.read()) >= 0) {
System.out.println("Got byte " + ch);
}
out.flush();
out.close();
socket.close();
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ClientSideTCPSocket client = new ClientSideTCPSocket();
client.run();
}
}
Server code
package sockets.com;
//Server Side
import java.net.*;
import java.io.*;
public class ServerSideTCPSocket {
public void run() {
try {
int serverPort = 4023;
ServerSocket serverSocket = new ServerSocket(serverPort);
serverSocket.setSoTimeout(900000);
while (true) {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to " + server.getRemoteSocketAddress());
//
int ch = 0;
while ((ch = server.getInputStream().read()) >= 0) {
System.out.println("Got byte " + ch);
}
// Write to output stream
OutputStream out = server.getOutputStream();
String s = "HELLO CLIENT";
byte[] bytes = s.getBytes("US-ASCII");
for (byte b : bytes) {
System.out.println(b);
out.write(b);
}
}
} catch (UnknownHostException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ServerSideTCPSocket srv = new ServerSideTCPSocket();
srv.run();
}
}
Would be grateful for any comments regarding why this is the case. Thank you.
A few things:
This block of code will loop forever until after the client closes his connection:
while ((ch = server.getInputStream().read()) >= 0) {
System.out.println("Got byte " + ch);
}
Then after the client closes his connection, the subsequent attempt to send "HELLO CLIENT" to the socket will generate an IO exception. That will trigger your server loop to exit.
The easy fix is to adjust your protocol such that the "message" is completed on some sentinel char. In my easy fix, I just adjusted it to break out when a ! was received.
Better to have each client session terminate on an ioexception instead of the entire server block. My refactor of your code:
public class ServerSideTCPSocket {
public void tryCloseSocketConnection(Socket socket) {
try {
socket.close();
}
catch(java.io.IOException ex) {
}
}
public void processClientConnection (Socket clientConnection) throws java.io.IOException {
int ch = 0;
while ((ch = clientConnection.getInputStream().read()) >= 0) {
System.out.println("Got byte " + ch);
if (ch == '!') {
break;
}
}
// Write to output stream
OutputStream out = clientConnection.getOutputStream();
String s = "HELLO CLIENT!";
byte[] bytes = s.getBytes("US-ASCII");
for (byte b : bytes) {
System.out.println(b);
out.write(b);
}
}
public void run() {
try {
int serverPort = 4023;
ServerSocket serverSocket = new ServerSocket(serverPort);
serverSocket.setSoTimeout(900000);
while (true) {
System.out.println("Waiting for client on port " + serverSocket.getLocalPort() + "...");
Socket clientConnection = serverSocket.accept();
try {
System.out.println("Just connected to " + clientConnection.getRemoteSocketAddress());
processClientConnection(clientConnection);
}
catch (java.io.IOException ex) {
System.out.println("Socket connection error - terminating connection");
}
finally {
tryCloseSocketConnection(clientConnection);
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ServerSideTCPSocket srv = new ServerSideTCPSocket();
srv.run();
}
}
Then adjust your client code's message to be:
String s = "HELLO SERVER!"; // the exclamation point indicates "end of message".
The client send a message, then the server receives the message and response the message. I don't know why the client can not read the response. If I remove the read part in client, the server can get the message. However for the following code, nothing work. Also I tried the flush(), it still doesn't work.
For client
public void run() {
try (Socket echoSocket = new Socket(HOSTNAME, Integer.parseInt(PORTNUMBER));
DataOutputStream dOut = new DataOutputStream(echoSocket.getOutputStream());
DataInputStream dIn = new DataInputStream(echoSocket.getInputStream());
) {
while (true) {
command = UI.commandQueue.take()
dOut.writeInt(Message.toByteArray(command).length);
dOut.write(Message.toByteArray(command));
int length;
while((length = dIn.readInt()) != 0) {
if (length > 0){
byte[] messagebyte = new byte[length];
dIn.readFully(messagebyte, 0, messagebyte.length);
try {
msg = Message.fromByteArray(messagebyte);
testDisplay(msg);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
testDisplay(msg);
}
}
}
}catch (UnknownHostException e) {
UI.display("Don't know about host " + HOSTNAME);
} catch (IOException e) {
UI.display("Couldn't get I/O for the connection to " + HOSTNAME);
}
}
For server
public void run() {
try (ServerSocket serverSocket = new ServerSocket(Integer.parseInt(PORT_NUMBER));
Socket clientSocket = serverSocket.accept();
DataOutputStream dOut = new DataOutputStream(clientSocket.getOutputStream());
DataInputStream dIn = new DataInputStream(clientSocket.getInputStream());) {
int length;
while ((length = dIn.readInt()) != 0) {
if (length > 0) {
byte[] messagebyte = new byte[length];
dIn.readFully(messagebyte, 0, messagebyte.length); // read the
// message
Message msg;
try {
msg = Message.fromByteArray(messagebyte);
testDisplay(msg);
dOut.writeInt(Message.toByteArray(msg).length);
dOut.write(Message.toByteArray(msg));
UI.display("ack sent");
} catch (Exception e) {
// TODO Auto-generated catch block
UI.display(e.getMessage());
}
}
}
} catch (IOException e) {
UI.display(
"Exception caught when trying to listen on port " + PORT_NUMBER + " or listening for a connection");
UI.display(e.getMessage());
}
}
Your server is echoing one response per request, but your client is trying to read more than one response per request, which it will never get, so it blocks.
I'm trying to write a simple proxy server, and I found this code online and I just want to try to run it see if it works, but when it creates a new socket, it got an ConnectException that says Connect refused. I'm using 'localhost' as the host and I tried several different ports but nothing works. What's the problem here, is it the code or my machine?
public static void runServer(String host, int remotePort, int localPort) throws IOException {
// Create the socket for listening connections
ServerSocket mySocket = new ServerSocket(localPort);
final byte[] request = new byte[1024];
byte[] reply = new byte[4096];
while (true) {
Socket client = null, server = null;
try {
client = mySocket.accept();
final InputStream streamFromClient = client.getInputStream();
final OutputStream streamToClient = client.getOutputStream();
try {
server = new Socket(host, remotePort);
} catch (IOException e) {
PrintWriter out = new PrintWriter(streamToClient);
out.print("Proxy server cannot connect to " + host + ":"
+ remotePort + ":\n" + e + "\n");
out.flush();
client.close();
continue;
}
final InputStream streamFromServer = server.getInputStream();
final OutputStream streamToServer = server.getOutputStream();
Thread t = new Thread() {
public void run() {
int bytesRead;
try {
while ((bytesRead = streamFromClient.read(request)) != -1) {
streamToServer.write(request, 0, bytesRead);
streamToServer.flush();
}
} catch (IOException e) {
}
}
};
t.start();
int bytesRead;
try {
while ((bytesRead = streamFromServer.read(reply)) != -1) {
streamToClient.write(reply, 0, bytesRead);
streamToClient.flush();
}
} catch (IOException e) {
}
streamToClient.close();
} catch (IOException e) {
System.err.println(e);
} finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
} catch (IOException e) {
}
}
}
'Connection refused' means exactly one thing: nothing was listening at the IP:port you tried to connect to. So it was wrong. The solution is to get it right, or to start the server if it hadn't been started.
You need to set timeout while reading data from socket, there is an example available here
I'm writing a simple asynchronous tcp server & client program and I am curious if it's possible that the method "waitForConnections" misses a connection because it's still busy with accepting the new connection or start listening to it.
I tested it with 250 clients and I didn't notice a connection loss.
The code i used for testing:
for(int counter = 0; 250 > counter; counter++)
{
final int localCounter = counter;
new Thread(() -> {
try {
Socket socket = new Socket(ip, port);
System.out.println("Connected!");
DataOutputStream out =
new DataOutputStream(socket.getOutputStream());
out.writeUTF("#" + localCounter + " hello server!");
listenToConnection(socket);
} catch (IOException e) {
e.printStackTrace();
}
}).start();
}
The server code:
public class Server extends Thread {
private ServerSocket serverSocket;
private final Integer port;
private int amountConnections = 0;
public Server(Integer port) {
this.port = port;
}
public void run() {
startServer(port);
}
private void startServer(Integer port) {
System.out.println("Server started!");
try {
serverSocket = new ServerSocket(port);
waitForConnections();
} catch (IOException e) {
e.printStackTrace();
}
}
private void waitForConnections() {
try {
Socket socket = serverSocket.accept();
System.out.println("New connection from: " + socket.getRemoteSocketAddress() + " - amount connections: " + amountConnections);
amountConnections++;
asyncListenToConnection(socket);
} catch (IOException e) {
e.printStackTrace();
}
finally{
waitForConnections();
}
}
// Creates a new thread for each connection to listen to
private void asyncListenToConnection(Socket socket) {
new Thread(() -> {
while (!socket.isClosed()) {
try {
DataInputStream in =
new DataInputStream(socket.getInputStream());
System.out.println("Connection: " + socket.getRemoteSocketAddress() + " says: " + in.readUTF());
} catch (IOException e) {
closeConnection(socket);
}
}
}).start();
}
private void closeConnection(Socket socket) {
if (!socket.isClosed() || socket.isConnected()) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("Connection: " + socket.getRemoteSocketAddress() + " has left");
}
}
}
I'm new to Java, threading and sockets so any tips are welcome including improving the code.
Since you call
serverSocket = new ServerSocket(port);
with no backlog parameter, according to the Oracle Documentation for ServerSocket at:
http://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#ServerSocket%28int%29
The maximum queue length for incoming connection indications (a
request to connect) is set to 50. If a connection indication arrives
when the queue is full, the connection is refused.
You can reduce the chances of this by increasing the backlog. If you also write the client code, you can have clients automatically retry after a connection refused.
This is my code:
import java.io.*;
import java.net.*;
public class proxy {
public static void main(String[] args) throws IOException {
try {
String host = "gamea.clashofclans.com";
int remoteport = 9339;
ServerSocket ss = new ServerSocket(0);
int localport = ss.getLocalPort();
ss.setReuseAddress(true);
// Print a start-up message
System.out.println("Starting proxy for " + host + ":" + remoteport
+ " on port " + localport);
// And start running the server
runServer(host, remoteport, localport,ss); // never returns
System.out.println("Started proxy!");
} catch (Exception e) {
System.err.println(e);
}
}
/**
* runs a single-threaded proxy server on
* the specified local port. It never returns.
*/
public static void runServer(String host, int remoteport, int localport, ServerSocket ss)
throws IOException {
// Create a ServerSocket to listen for connections with
System.out.println("Connected to Client!");
final byte[] request = new byte[2048];
byte[] reply = new byte[4096];
while (true) {
Socket client = null, server = null;
try {
// Wait for a connection on the local port
client = ss.accept();
System.out.println("Client Accepted!");
final InputStream streamFromClient = client.getInputStream();
final OutputStream streamToClient = client.getOutputStream();
// Make a connection to the real server.
// If we cannot connect to the server, send an error to the
// client, disconnect, and continue waiting for connections.
try {
server = new Socket(host, remoteport);
System.out.println("Client connected to server.");
} catch (IOException e) {
PrintWriter out = new PrintWriter(streamToClient);
out.print("Proxy server cannot connect to " + host + ":"
+ remoteport + ":\n" + e + "\n");
out.flush();
client.close();
System.out.println("Client disconnected");
continue;
}
// Get server streams.
final InputStream streamFromServer = server.getInputStream();
final OutputStream streamToServer = server.getOutputStream();
// a thread to read the client's requests and pass them
// to the server. A separate thread for asynchronous.
Thread t = new Thread() {
public void run() {
int bytesRead;
try {
while ((bytesRead = streamFromClient.read(request)) != -1) {
streamToServer.write(request, 0, bytesRead);
streamToServer.flush();
}
} catch (IOException e) {
}
// the client closed the connection to us, so close our
// connection to the server.
try {
streamToServer.close();
} catch (IOException e) {
}
}
};
// Start the client-to-server request thread running
t.start();
// Read the server's responses
// and pass them back to the client.
int bytesRead;
try {
while ((bytesRead = streamFromServer.read(reply)) != -1) {
streamToClient.write(reply, 0, bytesRead);
streamToClient.flush();
}
} catch (IOException e) {
}
// The server closed its connection to us, so we close our
// connection to our client.
streamToClient.close();
} catch (IOException e) {
System.err.println(e);
} finally {
try {
if (server != null)
server.close();
if (client != null)
client.close();
} catch (IOException e) {
}
}
}
}
}
When I run it I get to the message "Connected to client" (line 40) but after that nothing is happening in the window. I don't get the "Client has connected to the server message" so I assume the problem is somewhere around there?
Why is this happening? Does anyone know a fix?
I'm very new to java so please don't be harsh on me.
Your "Connected to Client!" message is misleading. At that point, you are starting your server and clients will soon be able to connect, but no clients have connected yet. Your program is waiting for
client = ss.accept();
to return. ServerSocket.accept waits for a connection to be made across the port. You need another thread, program, or computer to connect to this port to begin hosting them as a client. Make sure that this other thread, program, or computer is properly configured to connect to your open port. You likely need to either set ServerSocket to use a fixed port, or to determine what port it has opened a socket on and tell your other program what port to use.