Creating the Chat Server


To create the chat server, you need to create the following files:

  • ChatServer.java file

  • UAServer_Socket.java file

  • PRServer_Socket.java file

  • Msgbroadcast.java file

  • AppendUserList.java file

  • SocketCallback.java file

Creating the ChatServer.java File

The ChatServer.java file helps create a Command Line Interface (CLI)-based chat server. The chat server creates sockets to send and receive private and broadcast messages. To allow multiple users to connect to the chat server at the same time, you need to configure the chat server as non blocking.

Listing 2-1 shows the contents of the ChatServer.java file:

Listing 2-1: The ChatServer.java File
start example
 /*Imports java.net package class.*/ import java.net.*; /Imports java.nio package class.*/ import java.nio.*; import java.nio.channels.*; import java.nio.channels.spi.*; /*Imports java.util package class.*/ import java.util.*; /*Imports java.io package class.*/ import java.io.*; /* class ChatServer - Initializes all the chat server classes. This is the main class of the chat _ server.     Field:    SendAllPort: Stores the default port number.    SendPrivatePort: Stores the default port number.    UserList: Stores the list of users.    Method:    start_server(): Creates the objects of socket classes and starts the thread to run _    the server.    main(): Creates the object of the ChatServer class and call the Start_Server() _    method. */ public class ChatServer {    /*Declares the port numbers.*/    private int SendAllPort=9999;    private int SendPrivatePort=8888;    /*Creates and initializes the object of the ArrayList class.*/    ArrayList UserList=new ArrayList();    /*Defines the default constructor.*/       public ChatServer(){}    /*    start_server() - This method is called to start the chat server.     Parameters:   NA    Return Value: NA    */    public void start_server()    {       /*Creates the object of the UAServer_Socket class.*/       UAServer_Socket ua=new UAServer_Socket(SendAllPort,UserList);       /*Creates the object of the PRServer_Socket class.*/       PRServer_Socket p=new PRServer_Socket(SendPrivatePort,UserList);       /*Initializes and starts a new thread to create the socket for broadcasting.*/       new Thread(ua).start();       /*Initializes and starts a new thread to create the socket for private messaging.*/       new Thread(p).start();       System.out.println("Server is started. Now waiting for client requests...");    }    /*       main() - This method creates the main window of the user interface and displays it.       Parameters:       args[] - Contains any command line arguments passed.       Return Value: NA    */    public static void main(String[] args)     {       /*Creates and initializes the objects of the ChatServer class.*/       ChatServer cs=new ChatServer();       /* Calls the Start_Server() method. */       cs.start_server();    } } 
end example
 

Download this Listing .

In the above code, the main() method creates an instance of the ChatServer class and calls the start_server() method. The start_server() method creates the object of the UAServer_Socket and PRServer_Socket classes. The start_server() method then initializes and starts a new thread to create the socket to send and receive private and broadcast messages.

Creating the UAServer_Socket.java File

The UAServer_Socket.java file creates the socket connection to broadcast the messages. The UAServer_Socket class initializes and registers the broadcast socket to the chat server.

Listing 2-2 shows the contents of the UAServer_Socket.java file:

Listing 2-2: The UAServer_Socket.java File
start example
 /*Imports the java.net package class.*/ import java.net.*; /*Imports the java.net package class.*/ import java.nio.*; import java.nio.channels.*; import java.nio.channels.spi.*; /*Imports the java.util package class.*/ import java.util.*; /*Imports the java.io package class.*/ import java.io.*; /* Class UAServer_Socket - Creates the socket, registers and maps the socket to broadcast the _ message to all the end users connected in a chat session.    Fields:       Port - Contains the port number.       srvr_sckt_chnel - Creates the server socket channel.       sckt_manager - Manages the various sockets.       selkey - Selects the appropriate socket.       tdata - Stores the array of bytes.       broadcastMessage - Stores the messages.    Method:       init_socket() - Initializes the private messaging socket.       register_server() - Registers the server.       accept_connection() - Accepts the connections from the server.       read_Message() - Reads the message from the server socket.       closeRemoteChannel() - Closes all the remote channels.       write_Message() - Writes the messages to the server socket.       got_connection()  Retrieves the connection. */ public class UAServer_Socket implements Runnable {    /*Declares the port for broadcasting.*/    int port=9999;    /*Declares the object of the ServerSocketChannel class.*/    ServerSocketChannel srvr_sckt_chnel=null;    /*Declares the object of the Selector class.*/    Selector sckt_manager=null;    /*Declares the object of the Iterator class.*/    Iterator searcher=null;    /*Declares the object of the SelectionKey class.*/    SelectionKey selkey=null;    /*Declares the objects of the ArrayList class.*/    ArrayList broadcastMessage=new ArrayList();    /*Declares the object of the ByteBuffer class and allocate the size to the byte buffer.*/       ByteBuffer buffer=ByteBuffer.allocateDirect(1024);    int buflen=0;    byte[] tdata=null;    int conId=0;    int kichek =0;    /*     Defines the constructor that provides the port number as input.     */    public UAServer_Socket(int port)    {       this.port=port;    }    /* Defines the constructor that provides the port number and user list as input. */    public UAServer_Socket(int port, ArrayList conlist)    {       this.port=port;       broadcastMessage=conlist;    }    /* Defines the constructor that provides the user list as input. */    public UAServer_Socket(ArrayList conlist)    {       broadcastMessage=conlist;    }    /*    init_socket() - This method initializes the chat server.       Parameter: NA       Return Value: NA    */    public void init_socket() throws Exception    {       /*Opens the selector*/       sckt_manager=SelectorProvider.provider().openSelector();       /*Opens the server socket channel.*/       srvr_sckt_chnel=ServerSocketChannel.open();       /*Configures the server as NON Blocking.*/       srvr_sckt_chnel.configureBlocking(false);       /*Creates and initialize the object of the InetSocketAddress class.*/       InetSocketAddress fulnetaddr=new InetSocketAddress(port);       /*Binds the server socket.*/       srvr_sckt_chnel.socket().bind(fulnetaddr);       /*Calls the register()method.*/       register_server(srvr_sckt_chnel,SelectionKey.OP_ACCEPT);    }    /*       register_server() - This method registers the chat server.       Parameter:            Ssc: Represents the object of the ServerSocketChannel class.           selectionkey_ops: Integer type that determines the selection option.        Return Value: NA    */    public void register_server(ServerSocketChannel ssc,int selectionkey_ops)throws Exception    {       ssc.register(sckt_manager,selectionkey_ops);    }    /*    run() - This method calls the methods to initialize the socket and accept the connection of _    the sockets.       Parameters: NA       Return Value: NA    */       public void run()    {       try       {          /*Calls the initialization method.*/          init_socket();          /*Calls the method to accept the connection.*/          accept_connection();       }       catch(Exception ej)       {          ej.printStackTrace();       }    }    /*    accept_connection() - This method accepts the connection from the server.    Parameter: NA             Return Value: NA    */    public void accept_connection()throws Exception    {       while (true)          {             /*Calls the select() method of the Selector class.*/             kichek=sckt_manager.select();             if(kichek>=0)             {                /*                Initializes the object of the Iterator class by calling the selectedKeys() methodof the Selector class.                 */                searcher=sckt_manager.selectedKeys().iterator();                while(searcher.hasNext())                {                   /*Gets the next element.*/                   selkey=(SelectionKey)searcher.next();                   /*Removes the item from the searcher.*/                   searcher.remove();                   /*When the message provider gets new connection from user, this section is _                   executed.*/                      if(selkey.isAcceptable())                   {                      /*Creates and initializes the object of the ServerSocketChannel class to _                      get the channel withthe help of the channel() method.*/                      ServerSocketChannel server=(ServerSocketChannel)selkey.channel();                      /* Calls the got_connection() method.*/                      got_connection(server);                      System.out.println("connection establish");                } /* When the selector provider gets the stream for reading by the server from end user, this _ section is executed.*/ else if(selkey.isReadable())             {                /*Calls the read_Message() method.*/                read_Message((SocketCallback)selkey.attachment());                }                 /*When the selector Provider gets the stream for writing to user, this section is executed.*/ else if(selkey.isWritable())                {                   /*Creates the object of the SocketCallback class and call the attachment() _                   method of the SelectionKey class.*/                   SocketCallback  Vsc=(SocketCallback)selkey.attachment();                   String m_essage="";                   if (Vsc.getString().length()>0)                   m_essage =Vsc.getString();                         if(Vsc.get_broad_msg().length()>0)                   m_essage +=Vsc.get_broad_msg();                   /* Calls the write_Message(). */                               write_Message(Vsc,m_essage);                   }                   }                }             else             break;                      }                }    /*    read_Message() - This method reads the messages from the server socket.       Parameter:         sc: Represents the object of the SocketCallback class.                 Return Value:         String: Returns a string value.    */    public String read_Message(SocketCallback sc)     {       try       {          if (sc.isValidUser())          {                /* Clears the buffer. */             buffer.clear(); /*Reads the bytes from the channel. */ int nbyte=sc.getChannel().read(buffer);             if(nbyte==-1)             {                /*Closes the channel. */                closeRemoteChannel(sc);                sc.getChannel().close();                return "";             }             if (nbyte>0)             {                /*Flips the buffer.*/                buffer.flip();                /*Initializes the object of the Byte class.*/                tdata=new byte[nbyte];                /*Retrieves the data from the buffer.*/                         buffer.get(tdata,0,nbyte);                /*Initializes the object of the Inner_checker class.*/                String s=new String(tdata);                if(tdata[0]==31)                {                      /*Initializes the object of the AppendUserList class.*/                   new AppendUserList(sc,broadcastMessage);                    return "";                }                else                {                   if (s.length()>0)                   {                   sc.addString(s);                   /*Initializes the object of the Msgbroadcast class.*/                   new Msgbroadcast(broadcastMessage,s,sc.getUserId());                   return s;                   }                }             }          }          else           {             /*Clears the buffer.*/             buffer.clear();                          /*Reads the bytes from the channel.*/             int             nbyte=sc.getChannel().read(buffer);             if(nbyte==-1)             {                /*Closes the channel.*/                closeRemoteChannel(sc);                sc.getChannel().close();                return "";             }             if (nbyte>0)               {                /*Flips the buffer.*/                buffer.flip();                /*Initializes the object of the Byte class.*/                               tdata=new byte[nbyte];                /*Retrieves the data from the buffer.*/                buffer.get(tdata,0,nbyte);                /*Initializes the object of the Inner_checker class.*/                new UAinnerChecker(sc,tdata,nbyte);                            }                         }             }       catch(IOException ex)       {          try          {             /*Calls the closeRemoteChannel() method.*/                         closeRemoteChannel(sc);                         /* Closes the channel. */                         sc.getChannel().close();                      }                      catch(IOException ec)                      {                         ec.printStackTrace();                      }                   }                   /*Returns a null string.*/       return "";       }       /*          closeRemoteChannel() - This method close the remote channel.             Parameter:              sCb: Represents the object of the SocketCallback class.                      Return Value: NA             */       public void closeRemoteChannel(SocketCallback sCb)    {       int i = broadcastMessage.indexOf(sCb);       if (i >= 0)        {          /*Removes the broadcast message from the list.*/          broadcastMessage.remove(i);       }    }    /*       write_Message() - This method writes the messages to the server socket.          Parameter:           sc: Represents the object of the SocketCallback class.                   msg: Stores the message.          Return Value: NA             */    public void write_Message(SocketCallback sc,String msg)throws Exception    {       if (msg.length()>0)       {          /*Calls the doBroadcast() method.*/          sc.doBroadcast();          /*Creates the object of the ByteBuffer class. Next, wraps the bytes that are retrieved          from the message.*/          ByteBuffer b=ByteBuffer.wrap(msg.getBytes());          /*Writes the byte buffer to the server socket.*/          sc.getChannel().write(b);          }       }    /*    got_connection() - This method gets the connection from the server.       Parameter:        server: Represents the object of the ServerSocketChannel class.       Return Value: NA             */    private void got_connection(ServerSocketChannel servr)throws Exception    {       /*Initializes the object of the SocketChannel class to accept the connection.*/       SocketChannel sc=servr.accept();       /*Sets the server to Non Blocking server.*/       sc.configureBlocking(false);       /*Registers the server socket with the selector.*/       SelectionKey skey=sc.register(sckt_manager,SelectionKey.OP_READSelectionKey.OP_WRITE);       /*Creates the object of the SocketCallback class.*/       SocketCallback callbk=new SocketCallback(sc);       skey.attach(callbk);       }    /*       finalize() - This method is invoked when message is read or sent.       Parameter: NA          Return Value: NA             */    public void finalize() throws IOException    {       /*Closes the server socket channel.*/                srvr_sckt_chnel.close();                /* Closes the selector. */                sckt_manager.close();    }    /*     Inner Class: UAinnerChecker - This class checks the user validity.       Methods:        run(): Runs the started threads.       Chk_Validity(): Checks the user validity.       Chk_Valid_User(): Checks user validation.    */    class UAinnerChecker extends Thread                   {       /* eclares the objects of the SocketCallback class.*/       SocketCallback u=null;       byte[] b=null;       int len=0;       /*Defines the constructor that takes the SocketCallback class object and integer type       value as parameters.*/       UAinnerChecker(SocketCallback call,byte[] b,int len)       {          this.u=call;          this.b=b;          this.len=len;          start();       }       /*          run() - This method is called when the thread is started to call the thread methods.              Parameters:   NA             Return Value: NA       */          public void run()       {          /*Calls the Chk_Validity() method.*/          Chk_Validity();       }       /*       Chk_Validity() - This method check the user validity.            Parameter: NA                      Return Value: NA                */       private void Chk_Validity()       {          /*Declares the objects of the String class.*/          String u_id="";          String pwd="";          String info="";          /* Declares the FLAGS. */          boolean id_flag=true;           boolean pwd_flag=true;          try          {             for (int x=0;x<len;x++)             {                if(id_flag)                {                   /*Checks the user name separator "28" in the string.*/                   if (b[x]==28)                   {                   id_flag=false;                   }                   else                   u_id+=(char)b[x];                }                else if(pwd_flag)                {                   /*Checks the password separator "29" in the string.*/                   if (b[x]==29)                   {                   pwd_flag=false;                   }                   else                   pwd+=(char)b[x];               }               else               info+=(char)b[x];             } /*Checks the chat user is valid or not.*/ if(Chk_Valid_User(u_id, pwd)) {    /*Calls the setUserId() method of the SocketCallback class.*/    u.setUserId(u_id);    /*Calls the setPwd() method of the SocketCallback class.*/    u.setPwd(pwd);    /*Calls the setUinfo() method of the SocketCallback class.*/    u.setUinfo(info);    /*Calls the ValidUser() method of the SocketCallback class.*/    u.ValidUser(true);    /*Increments the counter by one. */    conId++;    /*Calls the setConid() method of the SocketCallback class.*/    u.setConid(conId);    broadcastMessage.add(u); } else {    /*Closes the channel.*/    u.getChannel().close(); } } catch(Exception e3)          {             e3.printStackTrace();          }                 }       /*          Chk_Valid_User() - This method checks the user is valid or not.             Parameter:              Uid: Stores the user name.             pass: Stores the password.             Return Value: NA                */ public boolean Chk_Valid_User(String Uid,String pass)       {            return true;         }    }  } 
end example
 

Download this Listing .

In the above code, the UAServer_Socket class creates a socket on port 9999 that allows end users to send and receive broadcast messages and an updated user list. The methods defined in this code are:

  • run() : Calls the init_socket() method to initialize the socket and calls the accept_connection() method to accept the connection from the client.

  • init_socket() : Opens the selector using the openSelector() method of the Selector class and the server socket channel using the open() method of the ServerSocketChannel class. This method then configures the server as non blocking using the configureBlocking() method of the ServerSocketChannel class. The init_socket() method creates the object of the InetSocketAddress class at port 9999 and binds the socket to the channel at that server IP. Finally, this method calls the register() method of the ServerSocketChannel to register the server.

  • accept_connection() : Calls the select() method of the Selector class when the connection is established. This method then initializes the object of the Iterator class by calling the selectedKeys() method of the Selector class. If the message provider gets a new connection from the end user, the accept_connection() method creates and initializes the object of the ServerSocketChannel class to retrieve the channel using the getChannel() method. Next, the accept_connection() method calls the got_connection() method to get the connection. If the selector provider gets a stream to read the message from the chat user, the accept_connection() method calls the read_Message() method to read the message. If the selector provider gets the stream to write a message to the chat user, the accept_connection() method creates the object of the SocketCallback class and calls the attachment() method of the SelectionKey class. Finally, the accept_connection() method calls the write_Message() to write the message.

  • got_connection() : Initializes the object of the SocketChannel class to accept the connection and sets the server to non blocking using the configureBlocking() method. The got_connection() method then registers the server socket with the selector, creates the object of the SocketCallback class, and calls the attach() method of the SelectionKey class.

  • read_Message() : Checks end user validity using the isValidUser() method of the SocketCallback class. If the end user is valid, the read_Message() method clears the buffer and reads the bytes from the channel to the buffer. The read_Message() method then retrieves the data from the buffer and separates the user name and broadcast message from the incoming data. If the data received from the server is an instance of the user name, the read_Message() method initializes the object of the AppendUserList class to add the end user to the user list. If the data received from the server is an instance of a message, the read_Message() method initializes the object of the Msgbroadcast class. If the end user is not valid, the read_Message() method clears the buffer, calls the closeRemoteChannel() method, and initializes the object of the UAinnerChecker class.

  • write_Message() : Calls the doBroadcast() method of the SocketCallback class. The write_Message() method then creates the object of the ByteBuffer class and wraps the message bytes. Finally, the write_Message() method writes the byte buffer to the server socket.

  • closeRemoteChannel(): Removes all the messages stored in the broadcastMessage array list.

  • finalize() : Calls the close() method to close the server socket channel and selector.

The UAServer_Socket class consists of an inner class, UainnerChecker, which allows you to validate the user name and password. The methods defined in this inner class are:

  • run() : Calls the Chk_Validity() method. This method is invoked when the constructor of the UAinnerChecker class is executed.

  • Chk_Validity() : Sets the id_flag and pwd_flag for the user id and password and checks the end user validity using the Chk_Valid_User() method. After validation, the Chk_Validity() method calls the setConid() method of the SocketCallback class.

  • Chk_Valid_User() : Returns true if the user name and password you specify are valid.

Creating the PRServer_Socket.java File

The PRServer_Socket.java file creates the socket connection to send and receive private messages. The PRServer_Socket class initializes and registers the socket to the chat server.

Listing 2-3 shows the contents of the PRServer_Socket.java file:

Listing 2-3: The PRServer_Socket.java File
start example
 /*Imports the java.net package class.*/ import java.net.*; /*Imports the java.net package class.*/ import java.nio.*; import java.nio.channels.*; import java.nio.channels.spi.*; /*Imports the java.util package class.*/ import java.util.*; /*Imports the java.io package class.*/ import java.io.*; /* Class PRServer_Socket - Creates the socket, registers and maps the socket to send private _ messages to the specified end user.       Fields:       port: Contains the port number.       srvr_sckt_chnel: Creates the server socket channel.       sckt_manager: Manages the various sockets.       selkey: Selects the appropriate socket.       tdata: Stores the array of the bytes.       userName: Stores the name of the private message user.       privateMessage - Stores the messages.       Methods:       init_socket(): Initializes the private messaging socket.       register_server(): Registers the server.       run(): Runs the started threads.             accept_connection() - Accepts the connections from the server.             read_Message() - Reads the message from the server socket.             closeRemoteChannel() - Closes all the remote channels.             write_Message() - Writes the messages to the server socket.             got_connection() - Retrieves the connection.             finalize() - Finalizes the server connection. */ public class PRServer_Socket implements Runnable {    /*Declares the port for private messaging.*/    int port=8888;    /*Declares the object of the ServerSocketChannel class.*/    ServerSocketChannel srvr_sckt_chnel=null;    /*Declares the object of the Selector class.*/    Selector sckt_manager=null;    /*Declares the object of the Iterator class.*/    Iterator searcher=null;    /*Declares the object of the SelectionKey class.*/    SelectionKey selkey=null;    /*Declares the object of the ByteBuffer class and allocate the size to byte buffer.*/       ByteBuffer buffer=ByteBuffer.allocateDirect(1024);    /*Declares the objects of the ArrayList class.*/    ArrayList userName=new ArrayList();    ArrayList privateMessage = new ArrayList();    int conId=0;    int buflen=0;    byte[] tdata=null;    int kichek =0;    /* Defines the constructor that provides the port number as input. */    public PRServer_Socket(int port)    {       this.port=port;    }    /*Defines the constructor that provides the port number and user list as input.*/    public PRServer_Socket(int port, ArrayList conlist)    {       this.port=port;       userName=conlist;    }    /*Defines the constructor that provides the user list as input.*/    public PRServer_Socket(ArrayList conlist)    {       userName=conlist;    }    /*    init_socket() - This method initializes the chat server.    Parameter: NA    Return Value: NA    */    public void init_socket() throws Exception    {       /*Opens the selector.*/          sckt_manager=SelectorProvider.provider().openSelector();       /*Opens the server socket channel.*/       srvr_sckt_chnel=ServerSocketChannel.open();       /* Configures the server as NON Blocking.*/       srvr_sckt_chnel.configureBlocking(false);       /*Creates and initializes the object of the InetSocketAddress class.*/       InetSocketAddress fulnetaddr=new InetSocketAddress(port);       /*Binds the server socket.*/       srvr_sckt_chnel.socket().bind(fulnetaddr);       /*Calls the register()method.*/       register_server(srvr_sckt_chnel,SelectionKey.OP_ACCEPT);    }    /*       register_server() - This method register the chat server.          Parameter:           ssc: Represents the object of the ServerSocketChannel class.          selectionkey_ops: Integer type that determines the selection option.          Return Value: NA    */ public void register_server(ServerSocketChannel ssc, int selectionkey_ops)throws Exception    {       /*Calls the register() method of the ServerSocketChannel class*/       ssc.register(sckt_manager,selectionkey_ops);    }    /*       run() - This method is called when the thread is started.          Parameters:   NA          Return Value: NA    */       public void run()    {       try       {          /*Calls the initialization method.*/          init_socket();          /*Calls the method to accept the connection.*/          accept_connection();       }       catch(Exception ej)       {          ej.printStackTrace();       }    }    /*       accept_connection() - This method accepts the connection from the server.          Parameter: NA                   Return Value: NA    */    public void accept_connection()throws Exception    {       while (true)         {             /*Calls the select() method of the Selector class.*/          kichek = sckt_manager.select();          if(kichek >= 0)          {             /*Initializes the object of the Iterator class by calling the selectedKeys() method             of the Selector class.*/             searcher = sckt_manager.selectedKeys().iterator();             while(searcher.hasNext())             {                /*Gets the next element.*/                selkey = (SelectionKey)searcher.next();                /*Removes the item from the searcher.*/                searcher.remove();                /*When the message provider gets new connection from the end user, this section                is executed.*/                if(selkey.isAcceptable())                {                   /*Creates and initializes the object of the ServerSocketChannel class to get _                   the channel using the channel() method.*/                   ServerSocketChannel server=(ServerSocketChannel)selkey.channel();                   /*Calls the got_connection() method.*/                   got_connection(server);                   System.out.println("connection establish");                } /*When the selector provider gets the stream for reading by the server from the end user, this _ section is executed.*/ else if(selkey.isReadable())                {                   /*Calls the read_Message() method*/                   read_Message((SocketCallback)selkey.attachment());                } /* When selector Provider gets stream for writing to the end user, then this section is executed. */ else if(selkey.isWritable())                {                   /* Creates the object of the SocketCallback class and calls the attachment() _                   method of the SelectionKey class. */                   SocketCallback  vsc =(SocketCallback)selkey.attachment();                   String m_essage="";                   if (vsc.getString().length()>0)                   m_essage =vsc.getString();                   if(vsc.get_broad_msg().length()>0)                   m_essage +=vsc.get_broad_msg();                   /* Calls the write_Message(). */                   write_Message(vsc,m_essage);                }             }          }          else          break;       }    }    /* read_Message() - This method reads the messages from the server socket.       Parameter:  sc: Represents the object of the SocketCallback class                Return Value:        String: Returns a string value.    */    public String read_Message(SocketCallback sc)     {       try       {          /*Clears the buffer.*/          buffer.clear(); /*Reads the bytes from the channel.*/ int nbyte=sc.getChannel().read(buffer);          if(nbyte==-1)          {             /*Closes the channel.*/             sc.getChannel().close();             return "";          }          if (nbyte>0)          {             /* Flips the buffer. */             buffer.flip();             /*Initializes the object of the Byte class.*/             tdata=new byte[nbyte];             /*Retrieves the data from the buffer. */             buffer.get(tdata,0,nbyte);             /*Initializes the object of the Inner_checker class.*/             new Inner_checker(sc,tdata,tdata.length);          }        }       catch(IOException ex)       {          try          {             /*Calls the closeRemoteChannel() method.*/             closeRemoteChannel(sc);             /*Closes the channel.*/             sc.getChannel().close();          }          catch(IOException ec)          {             ec.printStackTrace();          }       }       /*Returns a null string.*/       return "";    }    /*       closeRemoteChannel() - This method close the remote channel           Parameter:        sCb: Represents the object of the SocketCallback class.                   Return Value: NA             */       public void closeRemoteChannel(SocketCallback sCb)          {             int i = userName.indexOf(sCb);             if (i >= 0)              {             /*Removes the user name from the list.*/                      userName.remove(i);                   }                   int j = privateMessage.indexOf(sCb);                   if (j >= 0)                    {                /*Removes the private message from the user list.*/                      privateMessage.remove(j);       }    }    /* write_Message() - This method write the messages to the server socket       Parameter:  sc: Represents the object of the SocketCallback class.                msg: Stores the message.       Return Value: NA             */ public void write_Message(SocketCallback sc,String msg)throws Exception    {       if (msg.length()>0)       {          /*Calls the doBroadcast() method.*/          sc.doBroadcast();          /*Creates the object of the ByteBuffer class. Next, wraps the bytes that are retrieved          from the message. */          ByteBuffer b=ByteBuffer.wrap(msg.getBytes());          /*Writes the byte buffer to the server socket.*/          sc.getChannel().write(b);       }    }    /* got_connection() - This method gets the connection from the server.       Parameter:  server: Represents the object of the ServerSocketChannel class.       Return Value: NA             */ private void got_connection(ServerSocketChannel servr)throws Exception    {       /*Initializes the object of the SocketChannel class to accept the connection.*/       SocketChannel sc=servr.accept();       /*Sets the server to Non Blocking server.*/       sc.configureBlocking(false);       /Registers the server socket with the selector.*/       SelectionKey skey=sc.register(sckt_manager,SelectionKey.OP_READSelectionKey.OP_WRITE);       /*Creates the object of the SocketCallback class.*/       SocketCallback callbk=new SocketCallback(sc);       privateMessage.add(callbk);       skey.attach(callbk);    }    /* finalize() - This method is invoked when message is read or sent.       Parameter: NA          Return Value: NA             */    public void finalize() throws IOException    {       /*Closes the server socket channel.*/       srvr_sckt_chnel.close();       /*Closes the selector.*/       sckt_manager.close();    }    /*        Inner Class: Inner_checker - This class checks the end user validity.             Methods:              run(): Runs the started threads.             readName(): Reads the user name.       storeMessage_on_Database(): Stores the messages.    */    class Inner_checker extends Thread                      {       /*Declares the objects of the SocketCallback class.*/       SocketCallback to_m=null;       SocketCallback from=null;       byte ib[]=null;       int blen=0;       /*Defines the constructor that takes the SocketCallback class object and integer type _       value as parameters.*/       public Inner_checker(SocketCallback isc,byte[] msgbyte,int mlen)             {                from=isc;                ib=msgbyte;                blen=mlen;                /*Calls the start() method.*/                start();             }       /*          run() - This method is called when the thread is started.             Parameters:   NA             Return Value: NA       */          public void run()       {          boolean V_U_chk=false;          /*Initializes the object of the Iterator class that gets the user name.*/          Iterator chkval=userName.iterator();          /*Gets the user id.*/          String fromName = "" + from.getUserId();          String[] s=null;          if(fromName.length()<1)          {             /*Calls the readName() method.*/             s=readName(ib,blen,1);             return;          }          else          {             /*Calls the readName() method.*/             s=readName(ib,blen,0);             /*Gets the user id.*/             fromName=from.getUserId();          }            while(chkval.hasNext())          {             to_m=(SocketCallback)chkval.next();             if(fromName.equals(to_m.getUserId()))             {                   V_U_chk=true;                   break;             }          }             if(!V_U_chk)          {             try             {             from.getChannel().close();             int iobj = privateMessage.indexOf(from);             if (iobj >= 0)                 {                   /*Removes private message from the privateMessage array list.*/                   privateMessage.remove(iobj);                }             return;             }             catch(Exception ec)             {                 ec.printStackTrace();             }          } /*Initiates the object of the Iterator class to iterate the private message.*/ Iterator n=privateMessage.iterator();          SocketCallback msgTo=null;          while(n.hasNext())          {             msgTo=(SocketCallback)n.next();             if(msgTo.getUserId().equals(s[0]))             {                /*Calls the append_broad_msg() message of the SocketCallback class.*/                msgTo.append_broad_msg(from.getUserId()+ ":"+s[1]);                /*Calls the storeMessage_on_Database() method.*/                storeMessage_on_Database(s[1],s[0],fromName);                break;             }          }       }       /*          readName() - This method reads the name of the user.              Parameter:              b: Represents a byte array.             len: Contains the length.             chk: Represents the chk integer.             Return Value: NA                */ private String[] readName(byte[] b,int len,int chk)       {          String tmp="";          int sindex=0;          byte t[]=null;          String tmpStr[]=new String[2];          String usrNAME="";          for(int x=0;x<len;x++)          {             /*Checks for read name separator.*/             if(b[x]==3)             {                      sindex=x;                break;             }             else              tmp+=(char)b[x];             }                if(chk==1)          {             for(int x=sindex+1;x<len;x++)             {                if(b[x]==3)                {                         sindex=x;                   break;                }                else  /*Reads from the end user.*/                usrNAME+=(char)b[x];             }             /*Sets user id.*/             from.setUserId(usrNAME);          }             int tmpval=len-sindex;             t=new byte[tmpval];          /*Copies the array.*/          System.arraycopy(b,sindex+1,t,0,tmpval-1);          tmpStr[0]=tmp;          /*Creates and initializes the object of the String class.*/          tmpStr[1]=new String(t);          /*Returns the user name array string.*/          return tmpStr;       };       /*          storeMessage_on_Database() - This method stores the messages on database.             Parameter:             u_msg: Contains the message.             to_clientID: Contains the sender user name.             from_id: Contains the receiver user name.             Return Value: NA       */ public void storeMessage_on_Database(String u_msg,String to_clientID,String from_id)       {          /*Inserts code here to implement this method.*/        };        }; } 
end example
 

Download this Listing .

In the above code, the PRServer_Socket class creates a socket on port 8888 to send and receive private messages. The methods defined in this code are:

  • run() : Calls the init_socket() method to initialize the socket and calls the accept_connection() method to accept the connection.

  • init_socket() : Opens the selector using the openSelector() method of the Selector class and opens the server socket channel using the open() method of the ServerSocketChannel class. The init_socket() method then configures the server as non blocking using the configureBlocking() method of the ServerSocketChannel class, and creates the object of the InetSocketAddress class at port 9999. Finally, this method binds the socket to the channel at that server IP and calls the register_server() method.

  • register_server() : Calls the register() method of the ServerSocketChannel to register the server.

  • accept_connection() : Calls the select() method of the Selector class and checks the value of a variable, kichek. This method then initializes the object of the Iterator class by calling the selectedKeys() method of the Selector class. If the searcher variable has more elements, the accept_connection() method gets the next element and removes the item from the searcher. If the message provider gets a new connection from the end user, this method creates and initializes the object of the ServerSocketChannel class to get the channel using the channel() method. Next, the accept_connection() method calls the got_connection() method to get the connection. If the selector provider gets the stream to read the message from the end user, the accept_connection() method calls the read_Message() method to read the message. If the selector Provider gets the stream to write the message that is to be sent by the chat server to the end user, the accept_connection() method creates the object of the SocketCallback class and calls the attachment() method of the SelectionKey class. This method then calls the write_Message() method to write the message.

  • read_Message() : Reads the bytes from the channel to the buffer and flips the buffer. This method then retrieves the data from the buffer and initializes the object of the Inner_checker class.

  • closeRemoteChannel() : Removes all the messages stored in the privateMessage array list and the user names stored in the userName array list.

  • write_Message() : Calls the doBroadcast() method of the SocketCallback class and creates the object of the ByteBuffer class. The write_Message() method then wraps the message bytes and writes the byte buffer to the server socket.

  • got_connection() : Initializes the object of the SocketChannel class to accept the connection. This method then sets the server to a non blocking server using the configureBlocking() method and registers the server socket with the selector. The got_connection() method creates the object of the SocketCallback class and calls the attach() method of the SelectionKey class.

  • finalize() : Calls the close() method to close the server socket channel and selector.

The above code uses an inner class, named Inner_checker, to send private messages. The methods defined in this inner class are:

  • run() : Sends and stores private messages in the database. This method calls the readName() method to read the name of the sender. If the names of the sender and receiver are identical, the run() method calls the break method. Otherwise, the run() method initializes the object of the Iterator class to iterate the private message and calls the append_broad_msg() message of the SocketCallback class to send the private message. The run() method calls the storeMessage_on_Database() method to store the messages in a database.

  • readName() : Reads the data string from the server and separates the user name from this string using a separator, 3. This method reads the name and calls the setUserId() method of the SocketCallback class.

Note  

The storeMessage_on_Database() method stores the messages in the database, but this method is not implemented in the above code. You can implement this method for future enhancements.

Creating the Msgbroadcast.java File

The Msgbroadcast.java file sends the message to all the end users connected to the chat server.

Listing 2-4 shows the contents of the Msgbroadcast.java file:

Listing 2-4: The Msgbroadcast.java File
start example
 /*Imports the java.util package class.*/ import java.util.*; /*    Class Msgbroadcast - Broadcasts the messages to all the end users connected in a chat session.   Field:    storer - Stores the user list.    sc - Stores the object of the SocketCallback class.    next - Contains the Iterator object.    msg - Contains the message.    userId - contains the name of the end user. */ public class Msgbroadcast extends Thread {    /*Declares the object of the ArrayList class.*/    ArrayList storer = null;    /*Declares the object of the SocketCallback class.*/    SocketCallback sc = null;    /*Declares the object of the Iterator class.*/    Iterator next = null;    /* Declares the object of the String class.*/    String msg = "";    String userId = null;    /*Defines the default constructor of the Msgbroadcast class.*/    Msgbroadcast(ArrayList store,String msg,String userId)    {       storer = store;       this.msg = msg;       this.userId = userId;       /*Calls the start() method of the Thread class. */       start();    }    /*       run() - This method is called when the thread is started.          Parameters:   NA          Return Value: NA    */       public void run()    {       /* Initializes the object of the Iterator class to get the user id from the user list. */       next=storer.iterator();       while(next.hasNext())       {          /* Gets the user id from the socket. */          sc=(SocketCallback)next.next();          /* Broadcasts the messages to all end users. */          sc.append_broad_msg(userId + ":" + msg);       }    } } 
end example
 

Download this Listing .

In the above code:

  • The constructor of the Msgbroadcast class calls the start() method of the Thread class to invoke the run() method.

  • The run() method initializes the object of the Iterator class to get the user name from the user list. The run() method also retrieves the user name from the server socket and calls the append_broad_msg() method of the SocketCallback class.

Creating the AppendUserList.java File

The AppendUserList.java file retrieves the user list from the server, adds a new end user to it, and returns the updated user list to the server.

Listing 2-5 shows the contents of the AppendUserList.java file:

Listing 2-5: The AppendUserList.java File
start example
 /* Imports the java.util package class. */ import java.util.*; /*    Class AppendUserList  This class stores the name of all the end users connected in the chat session.    Field:    sc: Contains the object of the SocketCallback class.    uL: Stores the user list in an array list.    Method:    run() - This method is called by the start() method of Thread class. This method adds the    user id. */ public class AppendUserList extends Thread {    /* Declares the objects of the SocketCallback class. */    SocketCallback csc=null;    SocketCallback sc=null;    /* Declares the object of the ArrayList class. */    ArrayList uL=null;    /* Defines default constructor of the AppendUserList class. */    public AppendUserList(SocketCallback csc,ArrayList UL)    {       this.csc=csc;       this.uL=UL;       /* Calls the start() method of the Thread class. */       start();    }    /* run() - This method is called when the thread is started.       Parameters:   NA       Return Value: NA    */       public void run() {    /*Creates and initializes the object of the Iterator class to get the user id from the user list.*/    Iterator next=uL.iterator();    /*Creates a string that contains the user id separator "31".*/    String s=""+(char)31;    while(next.hasNext())    {       /* Gets the user id from the socket. */       sc=(SocketCallback)next.next();       s=s+sc.getUserId()+(char)31;    }    /*Adds a user id to the user list.*/    this.csc.append(s);    } } 
end example
 

Download this Listing .

In the above code:

  • The constructor of the AppendUserList class calls the start() method of the Thread class that invokes the run() method.

  • The run() method creates and initializes the object Iterator class to get the user name from the user list.

  • The run() method also creates a string that contains the user id with separator, 31.

  • The run() method retrieves the user id from the socket and adds the user name to the user list.

Creating the SocketCallback.java File

The SocketCallback.java file contains the methods to provide connectivity between the client and the server. The SocketCallback class establishes a connection between the chat server and the chat client and gets the file channel to send messages to all the users connected to the chat server.

Listing 2-6 shows the contents of the SocketCallback.java file:

Listing 2-6: The SocketCallback.java File
start example
 /* Imports the java.nio package class. */ import java.nio.*; import java.nio.channels.*; /* Class PRServer_Socket - Uses the sockets to communicate with the chat client.    Fields:    soket: Contains the object of the SocketChannel class.    UserId: Contains the user id.    Pwd: Contains the password.    Uinfo: Contains the user information    broadcast_msg: Contains the broadcasting message.    Methods:    isValidUser(): Checks the end user is valid or not.    ValidUser(): Returns the valid user.    getChannel(): Returns the socket channel.    setUserId(): Sets the user id.    getUserId(): Retrieves the user id.    setPwd(): Sets the password.    getPwd(): Retrieves the password.    setUinfo(): Sets the user information.    getUinfo(): Retrieves the user information.    append(): Appends the message.    append_broad_msg(): Appends the broadcasting messages.    get_broad_msg(): Retrieves the broadcast messages.    addString(): Adds message string.    getString(): Retrieves the messages string.    getConid(): Returns the connection id.    doBroadcast(): Broadcasts the message to all user.    isBroadcast(): Checks message is broadcasted or not.    setConid(): Sets the connection id. */ public class SocketCallback  {    /*Declares the object of the SocketChannel class.*/    private SocketChannel soket=null;    /*Declares the objects of the String class.*/    private String str="";    private String UserId="";    private String Pwd="";    private String Uinfo="";    private int cid=0;    private boolean isvalid_user=false;    private boolean userMark=false;    private boolean msgbroadcast=false;    String broadcast_msg="";    /*Defines the default constructor.*/    public SocketCallback(SocketChannel sc)    {       soket=sc;    }    /* The isValidUser() implementation. */    public boolean isValidUser()    {       return isvalid_user;    }       /*The ValidUser() implementation.*/    public void ValidUser(boolean b)    {       isvalid_user=b;    }    /*The getChannel() implementation.*/    public SocketChannel getChannel()    {       return soket;    }    /*The setUserId() implementation.*/    public void setUserId(String u)    {       UserId=u;    }    /*The getUserId() implementation.*/    public String getUserId()    {       return UserId;    }    /*The setPwd() implementation.*/    public void setPwd(String u)    {       Pwd=u;    }    /* The getPwd() implementation. */    public String getPwd()    {       return Pwd;    }    /* The setUinfo() implementation. */    public void setUinfo(String u)    {       Uinfo=u;    }    /* The getUinfo() implementation. */    public String getUinfo()    {       return Uinfo;    }    /* The append() implementation. */    public void append(String s)    {       broadcast_msg=s+broadcast_msg;    }    /*The append_broad_msg() implementation.*/    public void append_broad_msg(String msg)    {       if (msg.length()>0)    {        broadcast_msg+=msg;    }    }    /*The get_broad_msg() implementation.*/    public String get_broad_msg()    {       return broadcast_msg;    }    /*The addString() implementation.*/    public void addString(String s)    {       str=s;    }    /*The getString() implementation.*/    public String getString()    {       String str1=new String(str);       str="";       return str1;    }    /*The getConid() implementation.*/    public int getConid()    {       return cid;    }    /*The doBroadcast() implementation.*/    public void doBroadcast(boolean chk)    {       msgbroadcast=chk;    }    /*The doBroadcast() implementation.*/    public void doBroadcast()    {       broadcast_msg="";    }    /* The isBroadcast() implementation. */    public boolean isBroadcast()    {                return msgbroadcast;    }    /* The setConid() implementation. */    public void setConid(int id)    {       cid=id;    } } 
end example
 

Download this Listing .

In the above code, the SocketCallback class implements all the methods that are invoked in the server classes. The methods defined in this code are:

  • isValidUser() : Checks whether or not the end user is valid. This method returns true if the end user is valid.

  • getChannel() : Returns the socket channel.

  • setUserId() : Sets the user name.

  • getUserId() : Retrieves the user name.

  • setPwd() : Sets the password.

  • getPwd() : Retrieves the password.

  • setUinfo() : Sets the user information.

  • getUinfo() : Retrieves the user information.

  • append() : Appends the message.

  • append_broad_msg() : Appends the broadcasting messages.

  • get_broad_msg() : Retrieves the broadcast messages.

  • addString() : Adds message string.

  • getString() : Retrieves the message string.

  • getConid() : Returns the connection id.

  • doBroadcast() : Broadcasts the message to all the end users.

  • isBroadcast() : Checks whether or not the message is broadcasted.

  • setConid() : Sets the connection id.




Java InstantCode. Developing Applications Using Java NIO
Java InstantCode. Developing Applications Using Java NIO
ISBN: N/A
EAN: N/A
Year: 2004
Pages: 55

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net