Link to home
Start Free TrialLog in
Avatar of player8
player8

asked on

Messenger like system!!!!!!!!!!!

Hi everyone,
            I am doing a client-server programming.
Consider the following:
Clients: c1,c2,c3,c4.
Server:s1.
    Suppose at first c1 gets connected to s1.Then suppose if i am having a combo box in the client side  that is used to display the ip-addressess of on-line clients nothing should be their as only one client c1 is available in the network.
Now suppose if another client c2 logs in and gets connected to s1,then the ipaddress of c2 should be immediately send to already on-line c1.So whenever a new client  gets connected to server ,that
clients ip-address should be send to all the previously on-line clients.
I have tried a code something similar to this but not meeting the actual purpose.
In the server part i have tried the following:(I am giving only the portion of code which i want to clarify):
query="Select * from clientdet where status='online'";
                  rs=stmt.executeQuery(query);
                while(rs.next()){
                      String strValue = rs.getString ( 3 ) ;
                  
                        pw.println ( strValue );
                                        }
                  pw.println ("done"  ) ;

client -side:

In client side in the click event of a command button i have the following code:
      while ( ( ipfromserver = br1.readLine () ) != null && ! ipfromserver.equalsIgnoreCase ( "done" ) ){
                                  //parr[i]=ipfromserver;
                                if(ipfromserver.equalsIgnoreCase("192.168.3.185"))
                                continue;                        
                                vlist.add(new String ( ipfromserver ) ) ;
                               // System.out.println("fff"+vlist(i));                        
                                //i++;
                         }
The problem with  my code is as follows:
Let c1 be the first to be connected to s1.Suppose c2 gets connected to s1,then
in c2's interface the combobox will contain the ip-address of already connected c1 but c1 will not contain the ip-adress of newly connected c2 or for that matter any clients after c1.Its just that i have not coded to meet the purpose.
Kindly help me with this.
Thank you.

Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

The principle is quite straightforward - you need to send to all clients on each connect/disconnect of a new client.

This line is dubious:

>>if(ipfromserver.equalsIgnoreCase("192.168.3.185"))

as i guess that's meant to be the ip address of a particular client. If so, that has two problems:

a. it's likely to change
b. you'd have to compile each client separately

The solution to that is not to send redundant info to the client in the first place

ASKER CERTIFIED SOLUTION
Avatar of Mayank S
Mayank S
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>>query="Select * from clientdet where status='online'";

Why are you maintaining this info in a db as a matter of interest?
Perhaps he has a database with a User table, which also has 'status' as a member. Yeah, it's a better idea to maintain it in a list or a Vector.
Avatar of player8
player8

ASKER

Hi mayankeagle,
       I am sorry,their was some technical
problem with net-connectivity.so,i could
not respond immediately.
Well u suggested to store all printwiter objects.Can u plz help me with coding!!
Thank you
Avatar of player8

ASKER

Hi mayankeagle,
        Well rather i would want u to provide some coding for
ClientReadThread and ServerReadThread.I have already used one thread.So,i am perplexed as to how to go for another one.
Player8.
I will not give you full-code. I will provide you with some snippets which you could use.

At the server-side, you must be starting a thread for every client, like:

new ServerThread ( socket ) ;

Now, at the client-side as well, you can start 2 threads.

Socket s = .... ; // this is where you make your socket at the client-side and attempt to connect to the server
new ClientRead ( s ) ;
new ClientWrite ( s ) ;

ClientRead would be a class which extends Thread or implements Runnable, and so would be ClientWrite. ClientRead would have a BufferedReader to read from the server, and it would continually read for messages in a while loop (using the readLine () method). Sameway, ClientWrite thread would be used when you want to write a message to the server.

>> Well u suggested to store all printwiter objects

At the server-side, something like:

private static Vector writers = new Vector () ;

// whenever a client logs in, you make a BufferedReader and PrintWriter from the socket. Then just add the PrintWriter:

synchronized ( writers )
{
  writers.add ( pw ) ;

}
Avatar of player8

ASKER

Hi mayankeagle,
        Thank u for those snippets.In the
server side i already have thread for accepting all clients.So,do u mean i should have another thread.Can u plz clarify.
No, you should not make another thread at the server. You can add to the Vector in the same thread where you make the BufferedReader and PrintWriter at the server-end. At the client-side, you need to start 2 threads in the way that I have shown.
Avatar of player8

ASKER

Hi mayankeagle,
      i will try as per ur suggestions and return tommorrow.Kindly
excuse me.
Avatar of player8

ASKER

Hi mayankeagle,
   i have made the following changes at the server side.Can u plz check whether
i have correctly done it.

      if((passwd.equals(pass))&&(userid.equals(id))&&Inett.equals(ipadd))
                                    {
                                                reply="Valid";
                                                stmt.executeUpdate("update clientdet set status='online' where ipaddress='"+Inett+"'");
                                  synchronized(writers){
                                  
                                  writers.add(pw);
                                  writers.add(br);                                     
                                  }
                                                break;
                                    }
                        else
                                    {
                                                reply="Invalid";
                                    }
You don't need to add br to it. You can just add pw (I'm assuming pw is already defined).

BTW, why are you addressing your comments only to me? There's a bigger expert listening to this page ;-)
Avatar of player8

ASKER

Well, i am not getting any clue as to how to proceed eventhough couple of experts have participated in this question.Can any one kindly explain my question in some detail.
Mayankeagle,eventhough other experts are seeing my question,no body seems to be interested,that is why i am keeping in touch with u.
Well, I already told you what to do regarding the writers in my last comment? I didn't think that you want to know more. Do you want to know something more? Have you tried the ClientRead and ClientWrite threads?

Don't add 'br' to the Vector.

Mayank.
Avatar of player8

ASKER

Well mayankeagle,i know that i am annoying u and help rendered by u everytime may be 200% for an excellent
student .But i am a weak student.Ur snippets may be highly useful,but i have not done multithreading programs of this level.This is quite tough for me.I really need guidance.If u can keep in touch with me i will be really benefited.
So,can i ask doubts to u?
Regarding clientread and clientwrite,i have not done anything as i am confused.
>> i know that i am annoying u

Not at all. You're in my best questioners' list if you click on my profile and see it.

>> But i am a weak student.

I don't think so (from your previous questions where I have seen your code).

>> Regarding clientread and clientwrite,i have not done anything as i am confused

I thought you have tried something. Anyway, you can try something like this:

class ClientRead extends Thread
{
  private BufferedReader br ;

  public ClientRead ( BufferedReader br )
  {
    this.br = br ;
  }

  public void run ()
  {
    while ( true )
    {
      String sCommandFromServer = br.readLine () ; // always listen for messages from the server
      // this String will hold the message that the server sends
      // do your processing

    }

  }

}

class ClientWrite extends Thread
{
  private PrintWriter pw ;

  public ClientWrite ( PrintWriter pw )
  {
    this.pw = pw ;
  }

  public void run ()
  {
    // use this thread for sending messages to the server
  }

}

Wherever you connect to the server at the client-side:

Socket s = new Socket ( "server_ip_address", port_no ) ;
new ClientRead ( new BufferedReader ( new InputStreamReader ( s.getInputStream () ) ) ) ;
new ClientWrite ( new PrintWriter ( s.getOutputStream (), true ) ) ) ;
Avatar of player8

ASKER

Hi mayankeagle,
       I saw ur resume and felt gr8 when i
came to know that u r an Indian.I am also an Indian.Anyhow,thanks 4 ur latest comment.I took a deep breath after going through it.I will try my best to understand ur latest snippets and try my best to ask sensible doubts.I will return
tomorrow.
Avatar of player8

ASKER

Hi mayankeagle,
       I am still not getting a clear picture.So,here are my doubts:

>>ClientWriteThread -> constantly writes messages to the server
>>snipett that u have provided for ClientWriteThread

1)My question is, are the above modules meant for informing to
   server that a client has logged in.
   
>>// whenever a client logs in, you make a BufferedReader and >>PrintWriter from the socket. Then just add the PrintWriter:

>>synchronized ( writers )
>>{
>>  writers.add ( pw ) ;
>>}

2)I am not able to appreciate the purpose of above lines.Why should i make a bufferedreader object and printwriter object and
what is the purpose of synchronizing objects.



>>At the server-side, maintain a static Vector or some form of >>static list, containing the PrintWriter objects you have obtained
>>(>> pw.println ( strValue ); -> all these pw's).

3)strValue is used to store on-line ipaddress in string format,so
what do u mean by
>> containing the PrintWriter objects you have obtained

>>- Whenever a client logs in, get all the PrintWriters and send a >>message to them about the newly logged-in client (this can be >>done in the same thread which is servicing the client). Then, >>obtain a PrintWriter using pw = new PrintWriter ( >>socket.getOutputStream (), true ) ; and add it to the Vector

4)>> get all the PrintWriters
     Since i have used a printwiter manytimes and flushed after use,i am confused with this point also.

>>ClientReadThread -> constantly writes messages to the server
>>snipett that u have provided for ClientReadThread
5)Are the above lines meant for reading only the ip-address server side or additional messages also.

Mayanakegle,i am very sorry for asking such silly doubts.The thing is that i am learning java on my own,their are no friends
with me to give a good company and i have not done multithreading programs in good effect.I will be grateful if somehow u could adjust with me.
Player8
>> My question is, are the above modules meant for informing to server that a client has logged in.
>> Why should i make a bufferedreader object and printwriter object and what is the purpose of synchronizing objects.

You already have a BufferedReader and a PrintWriter, right? I want you to use the same ones, and not to make new ones. You had a BufferedReader and a PrintWriter at the client-side. They are moved to the ClientWrite and ClientRead threads. The ClientWrite thread uses the PrintWriter for writing to the server. The ClientRead uses the BufferedReader to read from the server.

The Vector at the server-side contains the list of all PrintWriters. You will use it to send a message to the clients that a new client has logged-in. Synchronizing is necessary because the same object can be used from multiple threads. Just to ensure thread-safety.

Try the following code snippets. I have taken your code (from your previous question) and modified it a little:

public class Server
{
  public static Vector vList ;

  public static void main ( String args[] )
    throws Exception
  {
    vList = new Vector () ;
    ServerSocket ss = new ServerSocket ( 4444 ) ;

    while ( true )
    {
      Socket s = ss.accept () ;
      new ServerThread ( s ) ;

    } // end while

  } // end of main ()

} // class definition over

class ServerThread extends Thread
{
  private Socket s ;
  private PrintWriter pw ;
  private BufferedReader br ;
  private String address ;

  public ServerThread ( Socket s )
  {
    this.s = s ;

  } // end of constructor ()

  public void run ()
  {
    try
    {
      br = new BufferedReader ( new InputStreamReader ( s.getOutputStream (), true ) ) ;
      pw = new PrintWriter ( s.getOutputStream (), true ) ;
      address = s.getInetAddress ().getHostAddress () ;

      synchronized ( vList )
      {
        for ( int i = 0, iSize = vList.size () ; i ++ )
        {  // send a message to all other clients that this new client logged-in
          PrintWriter temp = ( PrintWriter ) vList.get ( i ) ;
          temp.println ( "Client at: " + address + " has logged in. " ) ;

        } // end for

        vList.add ( pw ) ; // add the print-writer to the Vector - to notify it when more clients log in after this one

      } // end of synchronized block

      while ( true )
      {
        String message = br.readLine () ;
        System.out.println ( "Message from: " + address + ": " + message ) ;

        if ( message.equalsIgnoreCase ( "EXIT" ) )
        {
          synchronized ( vList )
          {
            vList.remove ( pw ) ; // remove it from the list

            for ( int i = 0, iSize = vList.size () ; i ++ )
            {
              PrintWriter temp = ( PrintWriter ) vList.get ( i ) ;
              temp.println ( "Client at: " + address + " has logged out. " ) ;

            } // end for

          } // end of synchronized block

          break ;

        } // end if

      } // end while

    } // end of try block

    catch ( Exception e )
    {
      e.printStackTrace () ;

    } // end of catch block

  } // end of run ()

} // class definition over


Now, write a Client program. Make a separate thread to read from the server and to write to the server. Or for simplicity, let the main () thread write.

public class Client
{
  public static void main ( String args[] )
    throws Exception
  {
    Socket s = new Socket ( "127.0.0.1", 4444 ) ; // give what-ever IP address the server has
    ClientRead cr = new ClientRead ( new BufferedReader ( new InputStreamReader ( s.getInputStream () ) ) ) ;
    PrintWriter pw = new PrintWriter ( s.getOutputStream (), true ) ;
    Thread.sleep ( 4000 ) ;
    pw.println ( "HI" ) ;
    Thread.sleep ( 4000 ) ;
    pw.println ( "How're you doing? " ) ;
    Thread.sleep ( 4000 ) ;
    pw.println ( "I'm fine, thank you. " ) ;
    Thread.sleep ( 4000 ) ;
    pw.println ( "EXIT" ) ;
    cr.halt () ;

  } // end of main ()

} // class definition over

class ClientRead extends Thread
{
  private boolean running ;
  private BufferedReader br ;
 
  public ClientRead ( BufferedReader br )
  {
     running = true ;
     start () ;

  } // end of constructor ()

  public void halt ()
  {
    synchronized ( running )
    {
      running = false ;

    } // end of synchronized block

  } // end of halt ()

  public void run ()
  {
    synchronized ( running )
    {
      while ( running )
      {
        String s = br.readLine () ;
        System.out.println ( "Message from server: " + s ) ;

      } // end while

    } // end of synchronized block

  } // end of run ()

} // class definition over


Run the server program. Then run several clients together. See if the messages from the clients are received on the server and when a client logs in or logs out, whether the notifications are sent from the server to the other clients.

>> Mayanakegle,i am very sorry for asking such silly doubts.The thing is that i am learning java on my own

No problem. Good that you're learning on your own. Its the best way to learn.
Avatar of player8

ASKER

Hi mayankeagle,
          My labsession is getting over.I have met with the following errors:
Server.java:
-------------
Cannot resolve the symbol vList (ServerThread)
Cannot resolve the symbol iSize.

Client.java
------------
 synchronized ( running )

running is a boolean variable and not an object.so,i am getting an error.
I will catch u tomorrow.
player8
>> Cannot resolve the symbol vList (ServerThread)

Make it Server.vList in ServerThread.

>> Cannot resolve the symbol iSize.

In both the for loops that have iSize, use:

for ( int i = 0, iSize = vList.size () ; i< iSize ; i ++ )

>> synchronized ( running )

Ah, I didn't notice that when I wrote that code. You can omit the synchronized ( running ) blocks and see what output you get.


Avatar of player8

ASKER

Hi mayankeagle,
        I have my next lab session only on 9th so i will be able to interact u only after 8th.
I tried the latest comment but still getting error at server side:

D:\rajeshrajan\special>javac Server.java
Server.java:64: ';' expected
        for ( int i = 0, iSize = Server.vList.size () ; i ++ )
                                                             ^
Server.java:73: illegal start of expression
      } // end of synchronized block
      ^
Server.java:71: ')' expected
        Server.vList.add ( pw ) ; // add the print-writer to the Vector - to not
ify it when more clients log in after this one
                                 ^
Server.java:86: ';' expected
            for ( int i = 0, iSize = Server.vList.size () ; i ++ )
                                                                 ^
Server.java:93: illegal start of expression
          } // end of synchronized block
          ^
Server.java:91: ')' expected
            } // end for
             ^
Server.java:58: cannot resolve symbol
symbol  : constructor InputStreamReader (java.io.OutputStream,boolean)
location: class java.io.InputStreamReader
      br = new BufferedReader ( new InputStreamReader ( s.getOutputStream (), tr
ue ) ) ;
                                ^
Server.java:64: incompatible types
found   : int
required: boolean
        for ( int i = 0, iSize = Server.vList.size () ; i ++ )
                                                          ^
Server.java:86: incompatible types
found   : int
required: boolean
            for ( int i = 0, iSize = Server.vList.size () ; i ++ )
player8
I already corrected that in my last comment. You need to change the for loops to:

for ( int i = 0, iSize = vList.size () ; i< iSize ; i ++ )

>> br = new BufferedReader ( new InputStreamReader ( s.getOutputStream (), true ) ) ;

Remove the second parameter (true) and make it getInputStream ():

br = new BufferedReader ( new InputStreamReader ( s.getInputStream () ) ) ;

>> } // end of synchronized block
         
Well, if you remove the synchronized ( running ) { block, then you have to remove its closing brace too:

} // end of synchronized block -> REMOVE THIS AS WELL (only for synchronized ( running ) {

But on second thought - I would say: let all synchronized ( running ) blocks be there, but change them to - synchronized ( this ) {
Hi player8, how's it going?
Avatar of player8

ASKER

Hi mayankeagle,
   >> Hi player8, how's it going?
First of all ,Thank you very much for the above comment(April 4th).I am terribly sorry to return so late.I was away for a fortnight due to unavoidable personal reasons.
      I will have to look into the code send by u as i have lost touch.
I will return today itself and propably shortly.Once again sorry for making u wait.
Player8