I am trying to create a web proxy client in java. I stole this guys code and modified it to create a server and now a client so that the user can just download and run the client to connect to the server. I would just like this to run on the terminal but my future plans are to add a gui.
This is the server. This works straight out of the box as in you enter the ip in firefox and it will run just fine. TLDR: It parses the URL and forwards the data from the client to the server and vice versa.
Request Handler.java
/*
-----------------------------------------------------------------------------------------------
STOLEN FROM THIS MAN ON GITHUB
https://github.com/stefano-lupo/Java-Proxy-Server/blob/master/src/RequestHandler.java
-----------------------------------------------------------------------------------------------
*/
import java.awt.*;
import java.io.*;
import java.net.*;
import javax.imageio.*;
public class RequestHandler implements Runnable {
/**
* Socket connected to client passed by Proxy server
*/
Socket clientSocket;
/**
* Read data client sends to proxy
*/
BufferedReader proxyToClientBr;
/**
* Send data from proxy to client
*/
BufferedWriter proxyToClientBw;
/**
* Thread that is used to transmit data read from client to server when using HTTPS
* Reference to this is required so it can be closed once completed.
*/
private Thread httpsClientToServer;
/**
* Creates a RequestHandler object capable of servicing HTTP(S) GET requests
* #param clientSocket socket connected to the client
*/
public RequestHandler(Socket clientSocket){
this.clientSocket = clientSocket;
try
{
this.clientSocket.setSoTimeout(2000);
proxyToClientBr = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
proxyToClientBw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
}
catch (IOException e)
{
System.out.println("Error on IO Exception");
e.printStackTrace();
}
}
/**
* Reads and examines the requestString and calls the appropriate method based
* on the request type.
*/
#Override
public void run() {
// Get Request from client
String requestString;
try{
requestString = proxyToClientBr.readLine();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Error reading request from client");
return;
}
// Parse out URL
System.out.println("Request Received " + requestString);
// Get the Request type
String request = requestString.substring(0,requestString.indexOf(' '));
// remove request type and space
String urlString = requestString.substring(requestString.indexOf(' ')+1);
// Remove everything past next space
urlString = urlString.substring(0, urlString.indexOf(' '));
// Prepend http:// if necessary to create correct URL
if(!urlString.substring(0,4).equals("http")){
String temp = "http://";
urlString = temp + urlString;
}
// Check request type
if(request.equals("CONNECT")){
System.out.println("HTTPS Request for : " + urlString + "\n");
handleHTTPSRequest(urlString);
}
else
{
System.out.println("HTTP GET for : " + urlString + "\n");
sendNonCachedToClient(urlString);
}
}
/**
* Sends the contents of the file specified by the urlString to the client
* #param urlString URL ofthe file requested
*/
private void sendNonCachedToClient(String urlString){
try{
// Compute a logical file name as per schema
// This allows the files on stored on disk to resemble that of the URL it was taken from
int fileExtensionIndex = urlString.lastIndexOf(".");
String fileExtension;
// Get the type of file
fileExtension = urlString.substring(fileExtensionIndex, urlString.length());
// Get the initial file name
String fileName = urlString.substring(0,fileExtensionIndex);
// Trim off http://www. as no need for it in file name
fileName = fileName.substring(fileName.indexOf('.')+1);
// Remove any illegal characters from file name
fileName = fileName.replace("/", "__");
fileName = fileName.replace('.','_');
// Trailing / result in index.html of that directory being fetched
if(fileExtension.contains("/")){
fileExtension = fileExtension.replace("/", "__");
fileExtension = fileExtension.replace('.','_');
fileExtension += ".html";
}
fileName = fileName + fileExtension;
// Attempt to create File to cache to
boolean caching = true;
File fileToCache = null;
BufferedWriter fileToCacheBW = null;
try{
// Create File to cache
fileToCache = new File("cached/" + fileName);
if(!fileToCache.exists()){
fileToCache.createNewFile();
}
// Create Buffered output stream to write to cached copy of file
fileToCacheBW = new BufferedWriter(new FileWriter(fileToCache));
}
catch (IOException e){
System.out.println("Couldn't cache: " + fileName);
caching = false;
e.printStackTrace();
} catch (NullPointerException e) {
System.out.println("NPE opening file");
}
// Check if file is an image
if((fileExtension.contains(".png")) || fileExtension.contains(".jpg") ||
fileExtension.contains(".jpeg") || fileExtension.contains(".gif")){
// Create the URL
URL remoteURL = new URL(urlString);
BufferedImage image = ImageIO.read(remoteURL);
if(image != null) {
// Cache the image to disk
ImageIO.write(image, fileExtension.substring(1), fileToCache);
// Send response code to client
String line = "HTTP/1.0 200 OK\n" +
"Proxy-agent: ProxyServer/1.0\n" +
"\r\n";
proxyToClientBw.write(line);
proxyToClientBw.flush();
// Send them the image data
ImageIO.write(image, fileExtension.substring(1), clientSocket.getOutputStream());
// No image received from remote server
} else {
System.out.println("Sending 404 to client as image wasn't received from server"
+ fileName);
String error = "HTTP/1.0 404 NOT FOUND\n" +
"Proxy-agent: ProxyServer/1.0\n" +
"\r\n";
proxyToClientBw.write(error);
proxyToClientBw.flush();
return;
}
}
// File is a text file
else {
// Create the URL
URL remoteURL = new URL(urlString);
// Create a connection to remote server
HttpURLConnection proxyToServerCon = (HttpURLConnection)remoteURL.openConnection();
proxyToServerCon.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
proxyToServerCon.setRequestProperty("Content-Language", "en-US");
proxyToServerCon.setUseCaches(false);
proxyToServerCon.setDoOutput(true);
// Create Buffered Reader from remote Server
BufferedReader proxyToServerBR = new BufferedReader(new InputStreamReader(proxyToServerCon.getInputStream()));
// Send success code to client
String line = "HTTP/1.0 200 OK\n" +
"Proxy-agent: ProxyServer/1.0\n" +
"\r\n";
proxyToClientBw.write(line);
// Read from input stream between proxy and remote server
while((line = proxyToServerBR.readLine()) != null){
// Send on data to client
proxyToClientBw.write(line);
// Write to our cached copy of the file
if(caching){
fileToCacheBW.write(line);
}
}
// Ensure all data is sent by this point
proxyToClientBw.flush();
// Close Down Resources
if(proxyToServerBR != null){
proxyToServerBR.close();
}
}
// Close down resources
if(fileToCacheBW != null){
fileToCacheBW.close();
}
if(proxyToClientBw != null){
proxyToClientBw.close();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Handles HTTPS requests between client and remote server
* #param urlString desired file to be transmitted over https
*/
private void handleHTTPSRequest(String urlString){
// Extract the URL and port of remote
String url = urlString.substring(7);
String pieces[] = url.split(":");
url = pieces[0];
int port = Integer.valueOf(pieces[1]);
try{
// Only first line of HTTPS request has been read at this point (CONNECT *)
// Read (and throw away) the rest of the initial data on the stream
for(int i=0;i<5;i++){
proxyToClientBr.readLine();
}
// Get actual IP associated with this URL through DNS
InetAddress address = InetAddress.getByName(url);
// Open a socket to the remote server
Socket proxyToServerSocket = new Socket(address, port);
proxyToServerSocket.setSoTimeout(5000);
// Send Connection established to the client
String line = "HTTP/1.0 200 Connection established\r\n" +
"Proxy-Agent: ProxyServer/1.0\r\n" +
"\r\n";
proxyToClientBw.write(line);
proxyToClientBw.flush();
// Client and Remote will both start sending data to proxy at this point
// Proxy needs to asynchronously read data from each party and send it to the other party
//Create a Buffered Writer betwen proxy and remote
BufferedWriter proxyToServerBW = new BufferedWriter(new OutputStreamWriter(proxyToServerSocket.getOutputStream()));
// Create Buffered Reader from proxy and remote
BufferedReader proxyToServerBR = new BufferedReader(new InputStreamReader(proxyToServerSocket.getInputStream()));
// Create a new thread to listen to client and transmit to server
ClientToServerHttpsTransmit clientToServerHttps =
new ClientToServerHttpsTransmit(clientSocket.getInputStream(), proxyToServerSocket.getOutputStream());
httpsClientToServer = new Thread(clientToServerHttps);
httpsClientToServer.start();
// Listen to remote server and relay to client
try {
byte[] buffer = new byte[4096];
int read;
do {
read = proxyToServerSocket.getInputStream().read(buffer);
if (read > 0) {
clientSocket.getOutputStream().write(buffer, 0, read);
if (proxyToServerSocket.getInputStream().available() < 1) {
clientSocket.getOutputStream().flush();
}
}
} while (read >= 0);
}
catch (SocketTimeoutException e) {
}
catch (IOException e) {
e.printStackTrace();
}
// Close Down Resources
if(proxyToServerSocket != null){
proxyToServerSocket.close();
}
if(proxyToServerBR != null){
proxyToServerBR.close();
}
if(proxyToServerBW != null){
proxyToServerBW.close();
}
if(proxyToClientBw != null){
proxyToClientBw.close();
}
} catch (SocketTimeoutException e) {
String line = "HTTP/1.0 504 Timeout Occured after 10s\n" +
"User-Agent: ProxyServer/1.0\n" +
"\r\n";
try{
proxyToClientBw.write(line);
proxyToClientBw.flush();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
catch (Exception e){
System.out.println("Error on HTTPS : " + urlString );
e.printStackTrace();
}
}
/**
* Listen to data from client and transmits it to server.
* This is done on a separate thread as must be done
* asynchronously to reading data from server and transmitting
* that data to the client.
*/
class ClientToServerHttpsTransmit implements Runnable{
InputStream proxyToClientIS;
OutputStream proxyToServerOS;
/**
* Creates Object to Listen to Client and Transmit that data to the server
* #param proxyToClientIS Stream that proxy uses to receive data from client
* #param proxyToServerOS Stream that proxy uses to transmit data to remote server
*/
public ClientToServerHttpsTransmit(InputStream proxyToClientIS, OutputStream proxyToServerOS) {
this.proxyToClientIS = proxyToClientIS;
this.proxyToServerOS = proxyToServerOS;
}
#Override
public void run(){
try {
// Read byte by byte from client and send directly to server
byte[] buffer = new byte[4096];
int read;
do {
read = proxyToClientIS.read(buffer);
if (read > 0) {
proxyToServerOS.write(buffer, 0, read);
if (proxyToClientIS.available() < 1) {
proxyToServerOS.flush();
}
}
} while (read >= 0);
}
catch (SocketTimeoutException ste)
{
ste.printStackTrace();
}
catch (IOException e) {
System.out.println("Proxy to client HTTPS read timed out");
e.printStackTrace();
}
}
}
}
This is the client. It doesn't seem to work and I dont really understand why as it is just a modified version of the server.
Request Handler.java
/*
-----------------------------------------------------------------------------------------------
STOLEN FROM THIS MAN ON GITHUB
https://github.com/stefano-lupo/Java-Proxy-Server/blob/master/src/RequestHandler.java
-----------------------------------------------------------------------------------------------
*/
import java.awt.*;
import java.io.*;
import java.net.*;
import javax.imageio.*;
public class RequestHandler implements Runnable
{
/**
* Socket connected to client passed by Proxy server
*/
Socket clientSocket;
/**
* Read data client sends to proxy
*/
BufferedReader clientToClientBr;
/**
* Send data from proxy to client
*/
BufferedWriter clientToClientBw;
/**
* Thread that is used to transmit data read from client to server when using HTTPS
* Reference to this is required so it can be closed once completed.
*/
private Thread threads;
/**
* Creates a RequestHandler object capable of servicing HTTP(S) GET requests
* #param clientSocket socket connected to the client
*/
public RequestHandler(Socket clientSocket)
{
this.clientSocket = clientSocket;
try
{
this.clientSocket.setSoTimeout(2000);
clientToClientBr = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
clientToClientBw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
}
catch (IOException e)
{
System.out.println("Error on IO Exception");
e.printStackTrace();
}
}
/**
* Reads and examines the requestString and calls the appropriate method based
* on the request type.
*/
#Override
public void run()
{
// Get Request from client
String requestString;
try
{
requestString = clientToClientBr.readLine();
System.out.println(requestString);
sendToServer(requestString);
}
catch (IOException e)
{
e.printStackTrace();
System.out.println("Error reading request from client");
return;
}
}
private void sendToServer(String urlString) throws IOException
{
// Open a socket to the remote server
Socket proxyToServerSocket = new Socket("192.168.0.226", 8080);
proxyToServerSocket.setSoTimeout(5000);
// Client and Remote will both start sending data to proxy at this point
// Proxy needs to asynchronously read data from each party and send it to the other party
//Create a Buffered Writer betwen proxy and remote
BufferedWriter proxyToServerBW = new BufferedWriter(new OutputStreamWriter(proxyToServerSocket.getOutputStream()));
// Create Buffered Reader from proxy and remote
BufferedReader proxyToServerBR = new BufferedReader(new InputStreamReader(proxyToServerSocket.getInputStream()));
// Create a new thread to listen to client and transmit to server
ClientToServerHttpsTransmit clientToServerHttps = new ClientToServerHttpsTransmit(clientSocket.getInputStream(), proxyToServerSocket.getOutputStream());
threads = new Thread(clientToServerHttps);
threads.start();
// Listen to remote server and relay to client
try {
byte[] buffer = new byte[4096];
int read;
do
{
read = proxyToServerSocket.getInputStream().read(buffer);
if (read > 0)
{
clientSocket.getOutputStream().write(buffer, 0, read);
if (proxyToServerSocket.getInputStream().available() < 1)
{
clientSocket.getOutputStream().flush();
}
}
} while (read >= 0);
}
catch (SocketTimeoutException e) {
}
catch (IOException e) {
e.printStackTrace();
}
// Close Down Resources
if(proxyToServerSocket != null){
proxyToServerSocket.close();
}
if(proxyToServerBR != null){
proxyToServerBR.close();
}
if(proxyToServerBW != null){
proxyToServerBW.close();
}
if(clientToClientBw != null){
clientToClientBw.close();
}
}
}
/**
* Listen to data from client and transmits it to server.
* This is done on a separate thread as must be done
* asynchronously to reading data from server and transmitting
* that data to the client.
*/
class ClientToServerHttpsTransmit implements Runnable
{
InputStream proxyToClientIS;
OutputStream proxyToServerOS;
/**
* Creates Object to Listen to Client and Transmit that data to the server
* #param proxyToClientIS Stream that proxy uses to receive data from client
* #param proxyToServerOS Stream that proxy uses to transmit data to remote server
*/
public ClientToServerHttpsTransmit(InputStream proxyToClientIS, OutputStream proxyToServerOS)
{
this.proxyToClientIS = proxyToClientIS;
this.proxyToServerOS = proxyToServerOS;
}
#Override
public void run()
{
try
{
// Read byte by byte from client and send directly to server
byte[] buffer = new byte[4096];
int read;
do
{
read = proxyToClientIS.read(buffer);
if (read > 0)
{
proxyToServerOS.write(buffer, 0, read);
if (proxyToClientIS.available() < 1)
{
proxyToServerOS.flush();
}
}
} while (read >= 0);
}
catch (SocketTimeoutException ste)
{
ste.printStackTrace();
}
catch (IOException e)
{
System.out.println("Proxy to client HTTPS read timed out");
e.printStackTrace();
}
}
}
I think that the error is in the Request Handler for the Client as the error message I get on the client terminal is:
Wating for client to connect on port 8080
Got CONNECT www.youtube.com:443 HTTP/1.1
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.net.SocketInputStream.read(SocketInputStream.java:127)
at ClientToServerHttpsTransmit.run(RequestHandler.java:186)
at java.lang.Thread.run(Thread.java:748)
and this is the error for the terminal on the server:
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.readLine(BufferedReader.java:324)
at java.io.BufferedReader.readLine(BufferedReader.java:389)
at RequestHandler.run(RequestHandler.java:75)
at java.lang.Thread.run(Thread.java:748)
Error reading request from client
Related
I am developing a proxy server based on java. For simple http request, proxy server is working. But for HTTPS Connection, connection gets timed out. Here are the steps I did. I first read one line from input stream and created a socket connecting Server. After that I gave 200 Status to client. After that I asynchronously read and write between Client Socket and Server socket. But currently this isn't working and connection gets timedout and I couldn't debug the problem.
public class ProxyServer extends Thread {
private String host;
private int port;
private ServerSocket serverSocket;
private InputStream proxyToClientIP;
private OutputStream proxyToClientOP;
private InputStream proxyToServerIP;
private OutputStream proxyToServerOP;
private Socket socket;
private Socket socketFromProxyServer;
ProxyServer(ServerSocket serverSocket, Socket socket) {
this.serverSocket = serverSocket;
this.socket = socket;
this.start();
}
public void run() {
processInputRequest();
}
public void processInputRequest() {
try {
proxyToClientIP = socket.getInputStream();
proxyToClientOP = socket.getOutputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(proxyToClientIP));
String hostDetails = reader.readLine();
System.out.println(hostDetails);
boolean isConnect = false;
//Need to parse request and find req type as GET or CONNECT
//As of now we assume it to be Connect request
if (!isConnect) {
processGetRequest();
} else {
processConnectRequest();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void processConnectRequest() {
//Need to get host name from request. Currently Hardcoded for developing purpose
host = "harish-4072";
port = 8383;
try {
socketFromProxyServer = new Socket(host, port);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(proxyToClientOP));
writer.write("HTTP/1.1 200 Connection established\r\n" + "\r\n");
writer.flush();
proxyToServerOP = socketFromProxyServer.getOutputStream();
proxyToServerIP = socketFromProxyServer.getInputStream();
proxyRequest();
} catch (IOException ex) {
System.out.println(ex);
}
}
public void proxyRequest() {
try {
new Thread() {
#Override
public void run() {
try {
byte[] read = new byte[1024];
int in;
System.out.println("Reading");
while ((in = proxyToClientIP.read(read)) != -1) {
proxyToServerOP.write(read, 0, in);
proxyToServerOP.flush();
}
} catch (SocketException e) {
System.out.println(e);
} catch (IOException ex) {
}
}
}.start();
byte[] reply = new byte[1024];
int out;
System.out.println("Writing");
while ((out = proxyToServerIP.read(reply)) != -1) {
proxyToClientOP.write(reply, 0, out);
proxyToClientOP.flush();
}
} catch (IOException ex) {
}
public void processGetRequest() {
//
}
}
I first read one line from input stream and created a socket connecting Server. ... After that I asynchronously read and write between Client Socket and Server socket.
The problem is that you are reading only a single line while you would need to read the full HTTP request header from the client, i.e. everything up to the end of the request header (\r\n\r\n).
Because you fail to do so the unread parts of the HTTP request are forwarded to the server. But the server is expecting the start of the TLS handshake and these data confuse the server. This might result in hanging or aborting, depending on the content of the data and one the kind of server.
I have created a simple utility, that implements server and client. Server waits for incomming connection, client connects and if there are any files in folder on server - they are sending to client.
I used DataInput/OutputStreams - writeUTF/readUTF for sending messages between client and server, writeLong/readLong - to send file size, write/read to send data.
The problem is that when I run both client and server - working stucks after sending one or two files. But if I trace the client and server in IDE step-by-step it works great, and it also works if I transfer files with buffer size in one byte - so it works really slowly, but it does not stuck.
I use Eclipse IDE, jdk 1.7 on client side and 1.8 on server side (tried 1.7 also), Ubuntu linux and Windows 2003 Server on two instances of VMWare players.
I also tried to add Thread.sleep(10000) and flush() anything might be flushed, even added socket.setTcpNoDelay(true); but no result.
It looks like server sends the next file name and waits for echo() from client, but client does not get it and stucks on readUTF(). But, if I do it in manual mode step-by-step it works fine.
Any ideas? Thank you!
Client source:
/**
* Method receives a file from server
* #param outWriter
* #param inBufferedReader
* #param inStream
*
*/
private void receiveFileFromServer(DataOutputStream out, DataInputStream in) {
try {
String fileName = in.readUTF(); ///<----- stucks here *************
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info("Receiving file "+fileName);
}
out.writeUTF(fileName);
out.flush();
Long fileSize = in.readLong();
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info("Filesize "+fileSize);
}
out.writeUTF(fileSize.toString());
out.flush();
File localFile = new File(fileName);
FileOutputStream fileOS = new FileOutputStream(localFile);
byte[] buffer = new byte [2048];
int bytesRead = 0;
try {
for (int i = 0; i<fileSize/buffer.length; i++) {
bytesRead = in.read(buffer, 0, buffer.length);
fileOS.write(buffer,0, bytesRead);
}
bytesRead = in.read(buffer, 0, (int)(fileSize%buffer.length));
fileOS.write(buffer,0, bytesRead);
System.out.println("----------------------- "+bytesRead);
} catch (IOException e) {
awlConnectionLogger.error("Error reading file "+fileName);
};
fileOS.close();
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info("File received.");
}
} catch (IOException e) {
awlConnectionLogger.error("Error reading Stream or socket closed");
}
}
/**
* Method sends a #param command to server, waits for answer, then if answer is not null and equals #param answer it logs #param messageOk else #param messageError
* returns true if everything is ok, else returns false
* #param outWriter
* #param inBufferedReader
* #throws IOException
*/
private boolean sendCommandReceiveAnswer(String command, String answer, String messageOk,String messageError,
DataOutputStream out, DataInputStream in) throws IOException {
out.writeUTF(command); //Hello handshake
out.flush();
String data = in.readUTF();
if ((data!=null)&&(data.equals(answer))) {
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info(messageOk);
}
return true;
} else {
awlConnectionLogger.error(messageError);
return false;
}
}
/**
* Try to establish connection with the awl-server according to detected RDP session
* #param serverIP - ip address of server
* #param user - username
*/
private void establishConnection(String serverIP, String user) {
if (awlConnectionLogger.isInfoEnabled()) {
awlConnectionLogger.info("Trying to establish awl-connection to "+serverIP+" as "+user);
}
Integer remoteAwlPort = Integer.parseInt(Config.awlPort);
try (Socket awlServerSocket = new Socket(serverIP,remoteAwlPort)) {//Creating autocloseable socket
this.awlServerSocket = awlServerSocket;
DataOutputStream out = new DataOutputStream(awlServerSocket.getOutputStream());
DataInputStream in = new DataInputStream(awlServerSocket.getInputStream());
if (!sendCommandReceiveAnswer("Hello-awl-client", "Hello-awl-server", "Server hello OK.",
"Unknown server type. Closing thread.", out, in)) {
return;
}; //Hello handshake - return if not successful
if (!sendCommandReceiveAnswer(user, "User-ok", "Username sent.", "Error sending username. Closing thread.", out, in)) {
return;
} //Sending username
String hostName = InetAddress.getLocalHost().getHostName(); //Getting client local hostname
if (!sendCommandReceiveAnswer(hostName, "Hostname-ok", "Local hostname "+hostName+" sent. Ready to receive files.",
"Error sending hostname. Closing thread.", out, in)) {
return;
} //Sending hostname
awlServerSocket.setTcpNoDelay(true);
while (isActive) {
receiveFileFromServer(out, in); //receiving files
out.writeUTF("Ready");
out.flush();
}
} catch (UnknownHostException e) {
awlConnectionLogger.error("Error in server IP adress");
} catch (SocketException e) {
awlConnectionLogger.error("Problem accessing or creating Socket.");
} catch (IOException e) {
awlConnectionLogger.error("General IO Error or Socket closed");
};
}
Server source:
void Echo (DataInputStream in) {
String echo = null;
try {
echo = in.readUTF();
System.out.println("Echo:"+echo);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void sendToClient (File file, DataOutputStream out, DataInputStream in) {
System.out.println("Sending file name "+file.getName());
try {
out.writeUTF(file.getName());
out.flush();
Echo (in); //<--------- stucks here *******************
out.writeLong(file.length());
out.flush();
Echo (in);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Sending file");
byte [] buffer = new byte [2048];
FileInputStream fileIS = null;
try {
fileIS = new FileInputStream(file);
} catch (FileNotFoundException e) {
System.out.println("Error opening file "+file);
e.printStackTrace();
}
try {
Integer bytesRead;
int i = 0;
while((bytesRead=fileIS.read(buffer))>0) {
out.write(buffer, 0, bytesRead);
}
out.flush();
} catch (IOException e) {
System.out.println("Error reading file "+file);
e.printStackTrace();
};
System.out.println("File sent.");
try {
fileIS.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void run () {
DataOutputStream out = null;
DataInputStream in = null;
String data = null;
String user = null;
String clientHostName = null;
try {
socket.setTcpNoDelay(true);
out = new DataOutputStream(socket.getOutputStream());
in = new DataInputStream(socket.getInputStream());
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("New incoming connection thread starded.");
try {
data = in.readUTF();
if (data.equals("Hello-awl-client")) {
System.out.println("Client hello OK.");
out.writeUTF("Hello-awl-server");
out.flush();
user = in.readUTF();
System.out.println("User: "+user);
out.writeUTF("User-ok");
out.flush();
clientHostName = in.readUTF();
System.out.println("Client hostname: "+clientHostName);
System.out.println("Server hostname: "+InetAddress.getLocalHost().getHostName());
out.writeUTF("Hostname-ok");
out.flush();
System.out.println("Ready to send files.");
while (isActive) {
File file = new File(ServerConfig.pdfFolder+"//"+user);
if (!file.isDirectory()) {
System.out.println("Error in path to user directory. Exiting thread");
return;
}
File [] files = file.listFiles();
for (File fileItem:files) {
while (!fileItem.renameTo(fileItem)) {
Thread.sleep(1000);
}; //waits while file is not busy to send it
if (socket.isOutputShutdown()) {
out = new DataOutputStream(socket.getOutputStream());
}
sendToClient (fileItem, out, in);
if (fileItem.delete()) {
System.out.println("File deleted.");
} else {
System.out.println("File not deleted.");
}
data = in.readUTF();
System.out.println(data);
}
}
} else {
System.out.println("Unknown connection type. Closing thread.");
return;
}
} catch (IOException | InterruptedException e) {
System.out.println("Connection error or can't sleep thread. Closing thread.");
return;
}
}
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.
I have a program which reads and writes data from a LIS machine. I am reading data from a specific port and writing data to a database table. When I read data from a table and adding them into an Arraylist, it is adding duplicate record. I could not find the solution.
The code is following:
public class PacsMultiThread extends Thread{
private static Logger logger = Logger.getLogger(PacsMultiThread.class);
// instance for Server socket and Socket class
private ServerSocket serverSocket = null;
private Socket socket = null;
ServerParams params = Configuration.getConfig().getServerParams();
PacsMultiThread() {
super("PacsMultiThread");
try {
// listen on local port
serverSocket = new ServerSocket(Configuration.getConfig().getHostParams().getPort());
} catch (IOException e) {
logger.error("Could not listen on port: " + Configuration.getConfig().getServerParams().getPort() + ", " + e);
System.exit(1);
}
}
/*
* thread run method call
* #see java.lang.Thread#run()
* Mohammod Hossain
*/
public void run() {
logger.info("run method is calling... ");
if (serverSocket == null)
return;
while (true) {
try {
socket = serverSocket.accept();
logger.info("connection status: "+ socket.isConnected());
} catch (IOException e) {
logger.error("Accept failed: " + Configuration.getConfig().getServerParams().getPort() + ", " + e);
System.exit(1);
}
try {
// readData();
//calling new Thread for reading data from port
ReadHandler readThread = new ReadHandler(socket);
readThread.start();
// writeData(socket);
//calling new Thread for writing data into port
WriteHandler writeThread = new WriteHandler(socket);
writeThread.start();
} catch (Exception e) {
logger.error(e.getMessage());
}
}
}
public class WriteHandler extends Thread {
private static Logger logger = Logger.getLogger(WriteHandler.class);
private Socket socket;
ServerParams params = Configuration.getConfig().getServerParams();
OutputStream out = null;
public WriteHandler(Socket socketConnection){
super();
this.socket = socketConnection;
}
#Override
public void run() {
writeData(socket);
}
private void writeData(Socket socket){
/*
* calling writeData method for data write to port
* #param Socket socket
*/
logger.info("writeData method is called :: ");
try{
//calling client socket method for connect to server port
// logger.info(" client socket "+socket.getRemoteSocketAddress());
// check data exist in table in HL7001;
List<HL7001> orderList = new ArrayList<HL7001>();
PacsDao pacsDao = new PacsDao();
orderList = pacsDao.getAllOrder();
//PrintWriter pw = new PrintWriter(theOutput, false);
int msgCount = 0;
if(orderList.size() > 0){
for(int i = 0;i<orderList.size();i++){
logger.info("orderList.size(): " + orderList.size());
HL7001 model = orderList.get(i);
logger.info("message from HL7001 Table :: " +"Msg Order No: "+
model.getOrderNo() +"\n"+" msg no:"+ model.getHl7MsgNo()+"\n"+" message: "+model.getHl7Msg());
//for(HL7001 model:orderList){
String tableMessage = model.getHl7Msg();
// read ADT Message from Table HL7001;
//readADTMsg(tableMessage);
// logging TABLE MESSAGE data into file
StringBuffer transmitMsg = new StringBuffer();
transmitMsg
.append(START_OF_BLOCK)
.append(tableMessage)
.append(END_OF_BLOCK)
.append(CARRAIGE_RETURN);
// write data to port
socket = new Socket(Configuration.getConfig().getServerParams().getUrl(), Configuration.getConfig().getServerParams().getPort());
if(socket.isConnected()){
logger.info(socket.getRemoteSocketAddress()+" port is connected ");
HL7007 hl7007 = new HL7007();
hl7007.setMsgNo(model.getHl7MsgNo());
hl7007.setPortAdress(socket.getRemoteSocketAddress().toString() );
opeonSocketLog(hl7007);
}else{
logger.error("Server socket is not conneted");
}
out = socket.getOutputStream();
//InputStream in = socket.getInputStream();
out.write(transmitMsg.toString().getBytes());
// save file into directory
// logging TABLE MESSAGE data into file
if (params.isOutputOnFile()) {
//comment this line for performance issue
FileLogger.log2(transmitMsg.toString());
}
/** Write across the socket connection and flush the buffer */
out.flush();
out.close();
// insert into record from Table HL7001 to Table HL7003;
insertOrderModel(model);
msgCount++;
logger.info("msgCount "+ msgCount);
if (Configuration.getConfig().getServerParams().getWaitingOption().equals("1")) {
try{
Thread.sleep(1000);
}catch (InterruptedException e) {
logger.error("Wait for writing message into "+ e.getMessage());
}
}
}
}
}catch (Exception e) {
logger.error(e.getMessage());
e.printStackTrace();
}finally{
try {
logger.info("finally block is executed in write method ");
socket.close();
} catch (Exception e) {
logger.error(e.getMessage());
e.printStackTrace();
}
}
}
In the above write class at first I read records from a table , then adding into list . If record exists I am open a socket connection then write data into port and delete the following record. But sometimes I am getting more duplicate records
It's all happening twice. You are opening a socket to yourself (why?) so another pair of reader & writer is created, so ... You shouldn't communicate with yourself via TCP/IP: there is something seriously wrong with your design at this point.
You don't need a socket for each entry.
Use the one socket you accepted, send everything to that and only close it when you have finished.
I'm trying to run a simple multithreaded server that fetches a URL and also that allows browser to upload file to sever( GET and POST ) it fetches the webpage with GET I'm having trouble with POST, here is my WebServer I'm using for making upload work. Note: HttpRequest is another class that handles threads
import java.net.*;
import java.io.*;
public class WebServer
{
public WebServer(int port)
{
System.out.println("starting web server on port " + port);
ServerSocket serverSocket = null;
try
{
//create the server
serverSocket = new ServerSocket(port);
}catch(IOException ex)
{
System.out.println("could not open port " + port);
System.exit(1);
}
//loop indefinitely
while(true)
{
try
{
Socket connection = null;
connection = serverSocket.accept();
//accept the connection
//create a new thread, start it and return to the waiting state
HttpRequest request = new HttpRequest(connection);
Thread t = new Thread(request);
t.start();
}catch(IOException ex)
{
//fail if an error occurs
System.out.println("problem accepting connection");
System.exit(1);
}
}
}
public static void main(String[] args)
{
//simple validation for the port number
if(args.length != 1)
{
System.out.println("please specify a port");
System.exit(1);
}
int port = -1;
try
{
port = Integer.parseInt(args[0]);
}catch(NumberFormatException ex)
{
System.out.println("invalid port number");
System.exit(1);
}
WebServer server = new WebServer (port);
}
}
here is the Http implements runnable
import java.net.*;
import java.io.*;
public class HttpRequest implements Runnable
{
private DataInputStream input = null;
private Socket connection;
private static DataOutputStream output = null;
public HttpRequest(Socket connection)
{
this.connection = connection;
}
//required method so this can be used as a thread
public void run()
{
try
{
//try and get the streams
input = new DataInputStream(connection.getInputStream());
output = new DataOutputStream(connection.getOutputStream());
}
catch(IOException ex)
{
System.out.println("could not get input/output streams from connection: " + connection.toString());
return;
}
try
{
StringBuilder response = new StringBuilder("");
String request = input.readLine();
System.out.println("request: " + request);
String[] requestArray = request.split(" ");
//read off and ignore the rest of the input
//added so this can be tested with real browsers
while(input.available() != 0)
{
input.read();
}
if (requestArray.length != 3)
{
//request should be of the format GET /index.html HTTP/1.1, die if a bad request comes in
System.out.println("bad request: " + request);
return;
}else
{
//requested file should be the second entry, remove the leading '/'
File requestedFile = new File(requestArray[1].substring(1));
System.out.println("requested file: " + requestedFile);
//check the requested file exists
if(requestedFile.exists())
{
System.out.println("file found, sending response");
DataInputStream fileInput = new DataInputStream(new FileInputStream(requestedFile));
//output HTTP header, must be followed by two new lines
response.append("HTTP/1.1 200 OK\n\n");
String line = fileInput.readLine();
while(line != null)
{
response.append(line);
line = fileInput.readLine();
}
fileInput.close();
output.writeBytes(response.toString());
output.flush();
output.close();
Logger.writeToLog("Request: " + request + "\r\nResponse: " + response.toString());
}
else
{
System.out.println("file not found, sending 404");
response.append("HTTP/1.1 404 Not Found\n\n");
output.writeBytes(response.toString());
output.flush();
output.close();
}
}
}
catch(IOException ex)
{
System.out.println("cannot read request from: " + connection.toString() + ex.toString());
return;
}
catch(NullPointerException ex)
{
System.out.println("bad request: " + connection.toString());
return;
}
try
{
input.close();
output.close();
connection.close();
}
catch(IOException ex)
{
System.out.println("Can't close connection: " + connection.toString());
return;
}
}
}
Your problem is that your HttpRequest class is not implementing the HTTP protocol properly. For starters, you are assuming that all requests are GET requests, and you are ignoring the header lines that follow the request line.
What you need to do is read the HTTP 1.1 Specification ... thoroughly ... and rewrite your code so that it reads and processes requests, and generates responses according to how the spec says it should be done.
Alternatively, don't waste your time reinventing the wheel (probably incorrectly). Use an existing web container framework, or an existing HTTP protocol stack such as Apache HttpComponents.