#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    9
    Rep Power
    0

    Question TCP Two-Client-Server/Client Program not doing what I expected


    I am trying to create a 2-Client 1-Server program that communicates both clients between each other, so that if one client disconnects, the communication can be re-established without finding the new IP. If you need something like this, hopefully you can use this code. Latter I am planning to use this code to communicate two phones

    My code is mostly working, but when I disconnect one of the clients I get unexpected results, also, one of the clients is not receiving the correct data, which is weird since both clients have the same code. I've been working on this for days and it's getting me frustrated, please help!

    Sorry, guys I have to post the whole code for this one. Both Client and Server. Also, please note that in order for this code to work, you will need to change the ip address to your own machine and there needs to be two clients working or set a loopback at the server by adjusting the ports. Also, the reason I made a loop that sends data is because I need it to be constant data exchange between each client, for GPS updates and stuff like that (not yet included in the code). Hopefully I put enough comments on the code to make it more understandable, but if not, please let me know. Thanks!


    Code:
    //******SERVER*********
    //The reason I used one port to send and other to receive instead of one that does both, is because it will cause an
    //Address already in use exception. That's because the socket connected to that port will be accepted twice (once by
    // each thread).
    public class Server{
    	//You only need to select Port1Send, automatically Port1Receive will be equal to Port1S +100
    	//Port2S = Port1S + 1000 and Port2R = Port2S + 100. That is just so if they ports don't close,
    	//you only need to change one parameter instad of 4
    	//Example. if Port1S = 1000, Port1R = 1100
    	//			  Port2S = 2000, Port2R = 2100
    	private static final int Port1S = 1009,
    							 Port1R = Port1S+100; 
    	private static final int Port2S = Port1S+1000, 
    							 Port2R = Port2S+100; 
    	
    	public static void main(String[] args) {
    		System.out.println("Server Services Started");
    		//To do a loopback, try Resender(Port1R, Port1S) or Resender(Port2R, Port2S)
    		Thread oneToTwo = new Thread(new Resender(Port1R, Port2S, "Server 1"));//Receives data from Client1 and sends it to Client2
    		Thread twoToOne = new Thread(new Resender(Port2R, Port1S, "Server 2"));//Receives data from Client2 and sends it to Client1
    		twoToOne.start();
    		oneToTwo.start();
    		
    
    	}
    
    }
    Code:
    ///////Server Thread
    
    import java.io.*;
    import java.net.*;
    
    
    public class Resender implements Runnable {
    	private int sendPort, receivePort;	
    	ServerSocket sendServerSocket, receiveServerSocket;
    	String name = "Server";
    	
    	//Constructors set the Port from where they receive the data and 
    	//the port to where they send the data received. Also set the name. 
    	//If the name is not set, the default is Server
    	public Resender(int sendPort, int receivePort, String name){
    		this.sendPort = sendPort;
    		this.receivePort = receivePort;
    		this.name = name;
    	}
    	public Resender(int sendPort, int receivePort){
    		this.sendPort = sendPort;
    		this.receivePort = receivePort;
    	}
    	
    	@Override
    	public void run(){
    		try {
    			sendServerSocket = new ServerSocket(sendPort);
    			receiveServerSocket = new ServerSocket(receivePort);
    		} catch (IOException e1) {
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    		}
    		
    		while(true){//Loops keeps going trying to reconnect to Clients if they get disconnected
    			try{
    				
    				byte[] byteBuffer = new byte[256];
    				int recvMsgSize= 0;			
    				Socket receivingSocket = receiveServerSocket.accept();
    				Socket sendingSocket = sendServerSocket.accept();
    				
    				InputStream in = receivingSocket.getInputStream();
    				OutputStream out = sendingSocket.getOutputStream();
    				
    				try{ 
    					while((recvMsgSize = in.read(byteBuffer)) != -1)//reads the InputStream to the byteBuffer until a disconnect signal is received (-1 is received)
    					{
    						out.write(byteBuffer,0,recvMsgSize);//Writes the byteBuffer to the OutputStream
    					}
    				}catch(SocketException e){
    					System.out.println(name + ": Client Disconnected Abruptly");					
    				}
    				//After Disconnection, close the send and receive sockets.
    				receivingSocket.close();
    				sendingSocket.close();
    				
    			
    			}
    			catch(Exception e){
    				//If an exception is caught while creating sockets, break  the loop and print errors
    				e.printStackTrace();
    				break;
    			}
    		}
    		
    	}
    	
    
    }
    Code:
    //***********CLIENT*******************
    
    
    public class Client1 {
    	private final static String serversIP = "192.168.1.132";
    	//sendPort is the port on the server to which we send data
    	//receivePort is the port on the server from which we receive data
    	private final static int sendPort = 2009, receivePort = sendPort+100;
    	
    	public static void main(String[] args) {
    		//Two threads are created, one to send data, and one to receive
    		Thread sender = new Thread(new Sender(serversIP, sendPort));
    		Thread receiver = new Thread(new Receiver(serversIP, receivePort));
    		
    		sender.start();
    		receiver.start();
    		
    		
    		
    	}
    
    }
    Code:
    ////////////Client Sender Thread
    import java.io.IOException;
    import java.io.OutputStream;
    //import java.net.ConnectException;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    
    public class Sender implements Runnable{
    	private int port;
    	private String ip;
    	
    	//the constructor sets the servers ip address and port to which we send data
    	public Sender(String ip,int port){
    		this.port = port;
    		this.ip = ip;
    	}
    	@Override
    	public void run() {
    		Socket socket;
    		int i = 0;
    		while(true){
    		
    			try {
    				socket = new Socket(ip, port);
    				while(true){
    					i++;
    					String message = "Looped " + i + " times\n";//sends a different message every time for troubleshooting
    					byte[] byteBuffer = message.getBytes();//converts the message to bytes
    					
    					OutputStream out = socket.getOutputStream();
    					out.write(byteBuffer);//puts message into the outputStream
    					Thread.sleep(100);//Sleep for a while so not to use all the resources of the computer
    				}
    			} catch (UnknownHostException e) {
    				e.printStackTrace();
    			} catch (IOException e) {
    				System.out.println("Connection Refused by Server");
    			} catch (InterruptedException e) {
    				System.out.println("Thread was unable to sleep");
    			}
    		}//Loops again to send a new message\	
    		
    	}
    
    }
    Code:
    ///////////Receiver - Client Side thread
    import java.net.*;
    import java.io.*;
    
    
    public class Receiver implements Runnable{
    	private int port;
    	private String ip;
    	private static final int bufferSize = 256;
    	//the constructor sets the servers ip address and port from which we receive data
    	public Receiver(String ip,int port){
    		this.port = port;
    		this.ip   = ip;
    	}
    	@Override
    	public void run() {
    		Socket socket;
    		byte[] byteBuffer = new byte[bufferSize];
    		while(true){//loops forever
    			try {
    					socket = new Socket(ip, port);
    					InputStream in = socket.getInputStream();
    					
    					try{
    						while(true){//loops forever unless an exception is caught
    							Thread.sleep(100); //Sleep for a while so not to use all the resources of the computer
    							in.read(byteBuffer);//read from InputStream and put into byteBuffer
    							String received = new String(byteBuffer);//pass the byteBuffer to a String
    							System.out.println(received);//print the information received
    						}
    					}catch(SocketException e){
    						System.out.println("Socket Exception");	
    					}
    					socket.close();//close the socket. we will try to reconnect again 
    					Thread.sleep(100);//Sleep for a while so not to use all the resources of the computer
    					
    			} catch (UnknownHostException e) {
    				e.printStackTrace();
    			} catch (IOException e) {
    				System.out.println("Connection refused");
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		}//Loop again and try to reconnect
    		
    	}
    }
    This is what the code should do
    Ok, what should happen is the following: Run Server, Run Client (twice, with different port numbers) and then you should see messages From Client1 on Client2 Screen and Messages sent from Client2 on Client1 screen. If One client disconnects, connection is resumed as soon as it connects again, if the server disconnects, the same should happen. In fewer words, there should be data exchange between two clients, with the server connecting them.

    This is what actually Happens
    There is Data exchange between the client, but the wrong data goes to one of the clients (data is kind of scrambled, don't know why since is the same code for both clients).
    When One of the client disconnects and tries to re-connect, data is scrambled to both clients, not just one :/
    When the server disconnects, again the data scrambles
    Last edited by xenoepist; January 8th, 2012 at 05:30 PM. Reason: Not Enough COmments
  2. #2
  3. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,724
    Rep Power
    348
    When I execute the programs, what should I see?
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    9
    Rep Power
    0

    More Details


    Originally Posted by NormR
    When I execute the programs, what should I see?
    This is what the code should do
    Ok, what should happen is the following: Run Server, Run Client (twice, with different port numbers) and then you should see messages From Client1 on Client2 Screen and Messages sent from Client2 on Client1 screen. If One client disconnects, connection is resumed as soon as it connects again, if the server disconnects, the same should happen. In fewer words, there should be data exchange between two clients, with the server connecting them.

    This is what actually Happens
    There is Data exchange between the client, but the wrong data goes to one of the clients (data is kind of scrambled, don't know why since is the same code for both clients).
    When One of the client disconnects and tries to re-connect, data is scrambled to both clients, not just one :/
    When the server disconnects, again the data scrambles

    Thanks in advance for your help
    Last edited by xenoepist; January 8th, 2012 at 05:26 PM. Reason: Not clear enough
  6. #4
  7. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,724
    Rep Power
    348
    Could you write a main method that starts the code?
    Here's what I've tried but the code doesn't do anything past the few startup messages.
    Code:
       public static void main(final String[] args) {
          Thread t = new Thread(new Runnable() {
             public void run() {
                Server.main(args);
             }
          });
          t.start();
          Thread t1 = new Thread(new Runnable() {
             public void run() {
                Client1.main(args);
             }
          });
          t1.start();
    
          // Give the test 10 seconds to do its thing
          try{Thread.sleep(10000);}catch(Exception x){}
          System.exit(0);  // exit after test
       }
    Run Client (twice, with different port numbers)
    Where do you specify the port numbers. The classes do NOT take any parameters that I can see.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    9
    Rep Power
    0

    I am sorry, I'm not following


    Originally Posted by NormR
    Could you write a main method that starts the code?
    Here's what I've tried but the code doesn't do anything past the few startup messages.
    Code:
       public static void main(final String[] args) {
          Thread t = new Thread(new Runnable() {
             public void run() {
                Server.main(args);
             }
          });
          t.start();
          Thread t1 = new Thread(new Runnable() {
             public void run() {
                Client1.main(args);
             }
          });
          t1.start();
    
          // Give the test 10 seconds to do its thing
          try{Thread.sleep(10000);}catch(Exception x){}
          System.exit(0);  // exit after test
       }

    Where do you specify the port numbers. The classes do NOT take any parameters that I can see.
    The Server Class has the main method that runs the Resender class (resender being a Thread)

    The Client Class has the main method of the Sender and Receiver Classess (Sender and Receiver being Threads of the Client Class).

    So, here are the steps to make this code work:
    1) Put the Server class and the Resender Class into one folder, they complement eachother.

    2)Save two copies of Client class with the Sender and Receiver Classes onto another folder (or the same folder as the server, depends on how you prefeer. I have three different workspaces one with server and two with client.).

    3)Change the ip from 192.168.1.132 to "local host" on BOTH CLIENTS and change the sendPort variable on ONE of the Clients to sendPort = 1009 instead of 2009. The port number should be the only difference between the client programs. Of course, you could just do the thread twice on one client, but then you wouldn't be able to emulate only one client disconnecting.

    4) run the main methods (Server first, then the clients ... well, the order shouldn't matter, it suppose to work no matter what starts first

    5) That's it... after everything connects, you should see data sent from one client onto the other client's screen, but when one client disconnects, there are some unexpected things happening. Like: some times the end carriage at the end of the message is disregarded, or some times spaces are received with no text, etc... just kind of weird. I believe the problem might be on the buffer, but I guess I jumped onto sockets to early since I have just finished "Java for Dummies" LOL.

    Thanks for your help... I appreciate it
    Last edited by xenoepist; January 9th, 2012 at 05:15 AM. Reason: I overcomplicated things, I think
  10. #6
  11. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,724
    Rep Power
    348
    Can you make a class for testing with a main like I posted above so that I can test the code. You should make it a simple as possible for someone to test your code. The five steps you list have 4 too many.
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    9
    Rep Power
    0
    Originally Posted by NormR
    Can you make a class for testing with a main like I posted above so that I can test the code. You should make it a simple as possible for someone to test your code. The five steps you list have 4 too many.
    You are right! If you save all the threads into one folder, this code should work. It uses the classes that implement Runnable (Resender, Sender and Receiver) and does a loopback.

    If it works correctly, you should see the following:
    Looped 1 times

    Looped 2 times

    Looped 3 times

    and so on, but it seems that the "/n" character is lost since there is no space between the lines :/. Anyways, here it is:

    Code:
    import java.net.*;
    
    public class Tester {
    	private static int ServerSendPort = 5000;
    	private static int ServerReceivePort = 6000;
    	public static void main(String[] args) throws UnknownHostException {
    		InetAddress myAddress = InetAddress.getLocalHost();
    		String serversIP = myAddress.getHostAddress();
    		
    		//This is part of the Server, it should receive data from client1 and send it to client2,
    		//but for now, I have it in a loop so it sends back what it receives
    				Thread oneToTwo = new Thread(new Resender(ServerSendPort, ServerReceivePort, "Whatever Name You Want to give it:"));
    		//This thread are part of the Client, they Send and receive data to the server
    				Thread sender = new Thread(new Sender(serversIP, ServerReceivePort));
    				Thread receiver = new Thread(new Receiver(serversIP, ServerSendPort));
    				
    				oneToTwo.start();
    				sender.start();
    				receiver.start();
    		
    
    	}
    
    }
  14. #8
  15. Contributing User
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Aug 2010
    Location
    Eastern Florida
    Posts
    3,724
    Rep Power
    348
    Ok, when I used your main() as posted I get:
    Looped 1 times
    Looped 2 times
    Looped 3 times
    ....
    and many more

    it seems that the "/n" character is lost
    Where is the extra lineend "\n" added to the output to make the output skip a line?
  16. #9
  17. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2011
    Posts
    9
    Rep Power
    0
    Originally Posted by NormR
    Ok, when I used your main() as posted I get:
    Looped 1 times
    Looped 2 times
    Looped 3 times
    ....
    and many more


    Where is the extra lineend "\n" added to the output to make the output skip a line?
    Sorry for the late response, it's just that I did not get an e-mail so I thought there were no new replies. Anyways, I figured out what was going on. A bunch of messages were sent to the Socket without being read, so when a socket.read() was sent, all those stored messages got read at once so there was only println("Looped 1 times\nLooped 2 times\n....."). Since for my application that data is just old, I will disregard data that is of certain length.

    Also, I figured out how to make the sockets reconnect after the connection was lost, but since I tried a bunch of things, I'm still trying to clean up my code and check if there are any more details to fix.

    I think the code can be improved for Client to Client communications, such as chat or other things. If anyone wants to see my code, I'll be glad to post it. Thanks!

IMN logo majestic logo threadwatch logo seochat tools logo