Solved

Need to keep the tcp/ip client in wait state in java

Posted on 2010-08-12
15
558 Views
Last Modified: 2012-06-21
Hello guys....

I have Tcp/Ip client and server programs in java. When client connect to server, it needs to wait for a response from server. How do I do that.

My requirement is after the connection is established, client needs to wait for reponse from the server. I found wait method. But I don't know how to use it,

Thanks for the any help...
0
Comment
Question by:rakhy_rakey
  • 9
  • 6
15 Comments
 
LVL 35

Expert Comment

by:mccarl
ID: 33426356
Just attempt to read from the client socket that is created, and that call will block (ie. wait) until the server sends the response and return to your program with the response.
0
 

Author Comment

by:rakhy_rakey
ID: 33426914
Thanks Carl for the response.

But here in this scenario, I am going to have multiple clients. So if multiple clients connect to a server, then all clients established connections. Say after an hour or a day, if server wants to send some response to a particular client later some time, how can It identify the client. Ok...for now we assume that server identifies the client.

But for the above scenario to happen, that particular client should wait. Right ?

How can I achieve it.

Thanks...  
0
 
LVL 35

Expert Comment

by:mccarl
ID: 33426964
I don't really understand how the scenario relates to whether the client should wait or not from what you have written (feel free to explain in more detail), but it sounds like you know what you want.

The response that I gave above will make the client wait, performing a read operation at the client end will make it wait until the server sends something to the client and then you can do something with whatever it sends.

If we are still not understanding each other, maybe it would help to at least explain what the client is waiting for? What condition is supposed to stop the client from "waiting"?

By the way, the server can identify each client connection, because when each client connects a unique Socket object is created at the server end to represent the particular client connection that was just established. (Maybe you can post some code to further help explain what you are trying to do?)
0
 

Author Comment

by:rakhy_rakey
ID: 33430571
ok mccarl...let me explain you in a more detailed way and come to you as soon as possible after do some thing with it...

Thanks.
0
 

Author Comment

by:rakhy_rakey
ID: 33434485
hello carl..

My server program is in java and client program is in .net. I pasted both programs.

Please see the code below.

In that I have a new Socket object called ClientSocket is being created for every new client.

Say, I have a client connected to this server at port 10000. server program can reply to this client by sending a message. this is fine. Now one more client connected to this server program. now server is listening to recent client and replying to the recent client. Say, one more client connected to the server now, then server is listening to the recent client, this is 3rd client.

Now, if the server wants to talk to the first client. How can it talk to first client. what are the changes that I need to make in my java server program.

Your help is greatly appreciated cral. Please reply if you need some more explanation on this.
/*

 java TCP/Ip server program opens a port to listen for clients

*/

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.OutputStream;

import java.io.PrintWriter;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.Scanner;



class server

{

	 private static ServerSocket serverSocket;

	

	 public static void main(String args[])

	{

		new server(10000);

	}

	

	 server(int port)

	{

		

		 try

  		{	

		serverSocket = new ServerSocket(port, 50);

             System.out.println("Server waiting for client on port " + serverSocket.getLocalPort());

            while(true)

            {

            	 // accept connection

                

             Socket socket = serverSocket.accept();

            

             System.out.println("New client asked for a connection");

             TcpThread t1 = new TcpThread(socket);    // make a thread of it

             System.out.println("Starting a thread for a new Client");

             t1.start();

            }

			

		}

		catch(Exception e)

		{

			System.out.println(e.getMessage());

		}

	}

		

	class TcpThread extends Thread {

         // the socket where to listen/talk

         Socket ClientSocket;

       //  ObjectInputStream Sinput;

         DataOutputStream dos;

         DataInputStream dis;

         byte[] buffer = new byte[1000];

         byte[] b1 = null; 

         

         TcpThread(Socket socket) {

                 this.ClientSocket = socket;

         }

         public void run() {

                 /* Creating both Data Stream */

                 System.out.println("Thread trying to create Data Input/Output Streams");

                 try

                 {

                               

                	 while(true)

                	 {

                		 //BufferedReader bis1 = new BufferedReader(new InputStreamReader(System.in));

                		 Scanner in = new Scanner(System.in);

                		 String name = in.nextLine();



                 		byte[] b = name.trim().toString().getBytes();

                		 

                 	 dos = new DataOutputStream(ClientSocket.getOutputStream());

                 	 dos.write(b);

                	// String data = dis.readUTF();

                	 //System.out.println(data);

                	 

                   	 }

                   

                 }

                 catch (IOException e) {

                         System.out.println("Exception creating new Input/output Streams: " + e);

                         return;

                 }

              

               

         }	

 }



}









/*

 * Tcp/ip client program which connectes to server on port 10000

*/

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Net.Sockets;

using System.IO;



namespace SampleTcpIpClientForChangedVersion

{

    class Program

    {

        static void Main()

        {

            TcpClient client = new TcpClient("localhost", 10000);

            BinaryReader br = null;

            try

            {



                

              

               // StreamReader sr = new StreamReader(s);

             //   StreamWriter sw = new StreamWriter(s);



                byte[] b = new byte[1000];

               // sw.AutoFlush = true;

                //Console.WriteLine(sr.ReadLine());

                while (true)

                {

                    Stream s = client.GetStream();

                    br = new BinaryReader(s);

                    int count = br.Read(b, 0, b.Length);

                    System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();

                    string str = enc.GetString(b, 0, count);

                    Console.WriteLine(str);

                   

                }

                //   s.Close();

            }

            catch (Exception e)

            {

                Console.WriteLine(e.StackTrace);

            }

            finally

            {

                // code in finally block is guranteed 



                // to execute irrespective of 



                // whether any exception occurs or does 



                // not occur in the try block



                //client.Close();

                br.Close();

            }

        }

    }

}

Open in new window

0
 

Author Comment

by:rakhy_rakey
ID: 33443487
Hi guys...

for every client there is a new socket object created as shown in above java server program example. I tried to serialize the object. But there is no definition to serialize the socket object in java. so I used toString() method of the socket object to convert to socket object to string. I did that and saved in a file. the output is :
Socket[addr=/127.0.0.1,port=3834,localport=10000]

But I need to convert the above string to socket object to identify this particular client. How can I do that. Please reply as soon as possible. It is urgent.

Thanks alot.
0
 
LVL 35

Expert Comment

by:mccarl
ID: 33443561
Sorry, I haven't been able to reply sooner, but I wasn't able to check my email over the weekend.

From the code that you posted earlier, your problem isn't identifying which socket that you want to send data to, because each socket is being correctly stored in each thread that is starting up. Your problem is determining which thread to use to send the data. You are using a Scanner to get the input from the "stdin" stream and what I guess is happening is that each time you start a new thread (which happens each time a client connects) that new thread's Scanner is consuming the input that you type and the other threads aren't getting anything to send to their clients.

So my question at the moment is... is the use of Scanner just something that you are doing to test your code? The reason I ask is that you might be putting in a lot of effort to get this working with the Scanner objects, that you just won't need if in the long run, this data that is sent to the clients comes from somewhere else.

I guess what I am saying is that it may help to provide us with more of the big picture of what you are trying to do, so that we can provide more appropriate advice.
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 35

Expert Comment

by:mccarl
ID: 33443739
I have just run a quick test to confirm my thoughts on Scanner, and it looks like they were right. I started a number of threads which each created a Scanner object and tried to read from it, however only one threads scanner ever returned with the line typed in, and it appears fairly indeterminate as to which thread gets the input, sometimes it was the first thread started, sometimes it was the last, etc.

If that is really what you want to do (i.e. capture input from stdin with a Scanner), you would need to change the structure of your program. You could possibly start another different thread who's purpose was to read from the Scanner and then pass the input on to one/many/all "comms" threads (the threads that you are creating now after each client connects), and then each "comms" thread doesn't refer to the Scanner objects but instead waits for input from the one thread that manages the input and sends the data of to their respective client.

As I said though, if you were just using Scanner as a test, it is a bit of effort to go to just to get that working, and you may be better off jumping that and going straight to the "real" method of input that the server will use.
0
 

Author Comment

by:rakhy_rakey
ID: 33446804
Thank you carl for replying.

Yes, my problem is identifying threads only, for which particular server needs to reply.
I just use it to send message to particular client. In my real time scenario also, once the client gets connected, it needs to wait for some time like an hour or more to recieve message. Say some 1000 clients connected to server listeing on a port at once, they need to wait for some time. Once server gets a message for a particular client, it needs to identify the thread regarding particular client. Thats is the main problem. I used the scanner object fot this purpose only. In my realtime scenario also, my server program going to get message from database, which is analogous to my scanner object here.

Please see below, the updated java server program that I have with me right now.

In that what I am doing is: I am using toString() method of the object to convert object to string. I am able to do it successfully. But I am unable to convert that string to socket object. That is main problem.

The approach I tried before was: serialize the socket object and then deserialize it. But in java we can not serialize the socket object. This is the reason I had to go for converting the object to string format.

once again thanks carl for your time....
/*

 java TCP/Ip server program opens a port to listen for clients

*/

import java.io.DataInputStream;

import java.io.DataOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutput;

import java.io.ObjectOutputStream;

import java.io.Serializable;

import java.net.ServerSocket;

import java.net.Socket;

import java.util.Scanner;



class server implements Serializable

{

	 /**

	 * 

	 */

	private static final long serialVersionUID = 1L;

	private static ServerSocket serverSocket;

	

	public static void main(String args[])

		{

			new server(10000);

		}

		

	 server(int port)

	 	{

		

		 	try

		 		{	

		 			serverSocket = new ServerSocket(port);



		 			System.out.println("Server waiting for client on port " + serverSocket.getLocalPort());

		 			while(true)

					{

		            	// accept connection

		 			 Object socket = serverSocket.accept();

			            

		            // Socket socket = serverSocket.accept();

		             System.out.println("New client asked for a connection\n");

		             TcpThread t1 = new TcpThread((Socket) socket);    // make a thread of it

		             System.out.println("Starting a thread for a new Client\n");

		             t1.start();

		            }

			

		 		}

			catch(Exception e)

			{

				System.out.println("Exeption occured in server class constructor\n");

				e.printStackTrace();

			}

	 	}

		

	class TcpThread extends Thread implements Serializable {

        

		private static final long serialVersionUID = 1L;

		// the socket where to listen/talk

         Socket ClientSocket;

       //  ObjectInputStream Sinput;

         DataOutputStream dos;

         DataInputStream dis;

         byte[] buffer = new byte[1000];

       

         

         TcpThread(Socket socket) {

                 	//this.ClientSocket = socket;

                 // Serialize to a file

                 ObjectOutput out = null;;

				try {

				    File f = new File("filename.ser");

		           

						out = new ObjectOutputStream(new FileOutputStream(f));

						out.writeObject(socket.toString());						

						out.close();

				} catch (FileNotFoundException e1) {

					System.out.println("FileNotFoundException occured in TcpThread class constructor\n");

					e1.printStackTrace();

				} catch (IOException e1) {

					System.out.println("IOException occured in TcpThread class constructor\n");

					e1.printStackTrace();

				}

				catch(Exception e)

				{

					System.out.println("general exception occured in TcpThread class constructor\n");

					e.printStackTrace();

				}

         }

         public void run() {

                 /* Creating both Data Stream */

                 System.out.println("Thread trying to create Data Input/Output Streams\n");

                 try

                 {

                               

                	 while(true)

                	 {

                		 Socket ClientSocket1 = null;

                   		 Scanner in = new Scanner(System.in);

                		 String name = in.nextLine();

                	

                		    // Deserialize the object

                		    try {

                		 

                		    	 File file = new File("filename.ser");

                     		    ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file)); 

                     		   ClientSocket1 = (Socket)oin.readObject();                     	

                     		   oin.close();

                	

							} catch (ClassNotFoundException e) {

								System.out.println("ClassNotFoundException occured in run method of TcpThread class\n");

								e.printStackTrace();

							}

							catch(Exception e)

							{

								System.out.println("some Exception occured in while loop of run method\n");

								e.printStackTrace();				

							}

                		    in.close();

                		 

                		

                 		byte[] b = name.trim().toString().getBytes();

                		 

                 	 dos = new DataOutputStream(ClientSocket1.getOutputStream());

                 	 dos.write(b);

                   	 }

                   

                 }

                /* catch (IOException e) {

                         System.out.println("IOException creating new Input/output Streams: " + e);

                         return;

                 }*/

                 catch(Exception e)

                 {

                     System.out.println("Some Exception in run method\n");

                     e.printStackTrace();                                   	 

                 }

              

               

         }	

	}



}

Open in new window

0
 
LVL 35

Expert Comment

by:mccarl
ID: 33452065
A few things about what you have written in your last post...

Is it an actual expected condition to have 1000 client connected to the server at the same time? That is quite a lot. If so, would you categorize the communications to each client as fairly intermittent? ie. the server gets a message for a particular client (from the database) after some time (like an hour, you say), does it then start communicating heavily with the client, or could it possibly just wait another hour and then get another message to send to that client? If it is intermittent like this, I would probably suggest not using threads for each connection. Threads would really only be useful if you were communicating heavily to multiple clients at the same time. In what it sounds like would happen with your application, you would spawn 1000 threads but each one would only wake up non-very often send a small message and then sleep again.

So what I would say your best way to design your app would be to have one thread that listens to the server socket and accepts client connections and puts the resulting client sockets into a collection (probably a HashMap) and then another thread that "listens" or polls the database for new messages to send to clients.

What you are trying to do with serializing the sockets (or converting them to Strings and back) isn't going to work for you, because the actual socket object represents the actual connection to the client. What I mention in the previous paragraph is what you are probably trying to do (i.e store the sockets in a HashMap)

Somewhere in your server's initialisation you would create a new Map object...

   Map<String, Socket> socketMap = new HashMap<String, Socket>();

Then when your server "accepts" the client connection and gets a Socket object you would place that in the HashMap with some identifying key...

   socketMap.put(socket.toString(), socket);

And then in another thread where you get a message that should be directed to a particular client, you can retrieve the socket from the map and then send the message to the client

   public void sendMessageToClient(String clientId, String message)
   {
      Socket socket = socketMap.get(clientId);
     
      // Send the message to the client on this socket
      // Psuedocode:
      //  socket.send(message);
   }


With this, since there will be two threads; one that puts sockets into the map after the accept() returns and one that polls the database (or Scanner in testing) and sends message to sockets in the map; the access to the map will need to be synchronized.

I hope this can help to get you closer to a workable solution.
0
 

Author Comment

by:rakhy_rakey
ID: 33466570
Hello Carl...

Thank you very much for the nice reply.

I also got to this approach finally. Any way we both are thinking in same way towards the solution. Thanks for giving hashmap idea. Let me get back to you as soon as possible after working and implemeting this one.

Thanks,
Rakhy.
0
 

Author Comment

by:rakhy_rakey
ID: 33466631
Carl...

I am going to have 2 million customers in production. What is your idea about this to maintain connection to 2 million cusotmers using hashmap mechanism, sockets and threads.

I hope your vauable reply is defnitely going to help me out in this scenario.

Thanks alot....

0
 
LVL 35

Accepted Solution

by:
mccarl earned 500 total points
ID: 33472467
2 million???????????

Wow, well you would not be able to even accept that many connections on the one machine. You only have a max 65536 ports to connect with and then some of these will already be used. And then, you would have to think of the processing/memory/etc resources needed to keep connections on that number of ports. Even (and I am not saying that this would be possible) if you were able to maintain 40000 connections on one machine, you would still need a farm of 50 servers to get up to 2 million. And then all the load balancing, etc functionality to go with it would have to be considered.

None of this I am very knowledgeable on nor is it related to the original question, so I would suggest opening a new question so that you can get the appropriate help.
0
 

Author Comment

by:rakhy_rakey
ID: 33481168
yeah...let me come to you again by putting our proposal infront of team.

Thanks carl.
0
 

Author Comment

by:rakhy_rakey
ID: 33485019
hello cral...

they skipped the socket communication in this phase of development. So any way thanks alot for the information. You really gave good suggesstions. Any way I want to vote for you for this question and I want to close now.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Article by: rfc1180
The Maximum Segment size (MSS) is an important consideration when troubleshooting connectivity via the Internet/Intranet. As the packets are routed via the Internet/Intranet, the packets must traverse through multiple routers in the path between two…
Creating an OSPF network that automatically (dynamically) reroutes network traffic over other connections to prevent network downtime.
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now