| Navigate Concurrent Programming topic: | 
In 1990s, the trend was moving away from Mainframe computing to Client/Server as the price of Unix servers dropped. The database access and some business logic were centralized on the back-end server, collecting data from the user program was installed on the front-end users' "client" computers. In the Java world there are three main ways the front-end and the back-end can communicate.
- The client application uses JDBC (Java DataBase Connectivity API) to connect to the data base server, (Limited business logic on the back-end, unless using Stored procedures).
- The client application uses RMI (Remote Method Invocation) to communicate with the back-end.
- The client application uses a socket connection to communicate with the back-end.
Socket Connection Example

This page shows an example of a socket connection.
Create a Server
The Java language was developed having network computing in mind. For this reason it is very easy to create a server program. A server is a piece of code that runs all the time listening on a particular port on the computer for incoming requests. When a request arrives, it starts a new thread to service the request.
See the following example:
Listening on a port
- ComServer
- class is for listening on a port for a client.
|  | Code listing 1.1: ComServer import java.net.ServerSocket;
/**
 * -- Main Server Class; Listening on a port for client; If there is a client,
 * starts a new Thread and goes back to listening for further clients. --
 */
public class ComServer 
{
static boolean  GL_listening = true;
   /**
    * -- Main program to start the Server --
    */
   public static void main(String[] args) throws IOException
   {
      ComServer srv = new ComServer();
      srv.listen(); 
   } // --- End of Main Method ---
   /**
    * -- Server method; Listen for client --
    */
   public int listen() throws IOException
   {
    ServerSocket serverSocket = null;
    int iPortNumber = 9090;
       // --- Open the Server Socket where this should listen ---
       try {
           System.out.println( "*** Open the listening socket; at:"+ iPortNumber + " ***" );
           serverSocket = new ServerSocket( iPortNumber );
       } catch (IOException e) {
           System.err.println("Could not listen on port:"+iPortNumber );
           System.exit(1);
       }
       while ( GL_listening )
       {
        ComServerThread clientServ; 
           // --- Listening for client; If there is a client start a Thread -
           System.out.println( "*** Listen for a Client; at:"+ iPortNumber + " ***" );
           clientServ = new ComServerThread( serverSocket.accept() );
           // --- Service a Client ---
           System.out.println( "*** A Client came; Service it ***" );
           clientServ.start();   /* --- Use for multy Threaded --- */
      //     clientServ.run();    /* --- Use for Single Threaded --- */
       }
       // --- Close the Server socket;  Server exiting ---
       serverSocket.close();
    return 0;
   } // --- End of listen Method --- 
}  // --- End of ComServer Class ---
 | 
- ServerSocket( iPortNumber )
- Creates a server socket, bound to the specified port.
- serverSocket.accept()
- Listens for a connection to be made to this socket and accepts it. The method blocks until a connection is made. It returns a new Socket.
Service One Client
- ComServerThread
- This class extended from a Thread is responsible to service one client. The Socket connection will be open between the client and server. A simple protocol has to be defined between the client and server, the server has to understand what the client wants from the server. The client will send a terminate command, for which the server will terminate the socket connection. The ComServerThread class is responsible to handle all client requests, until the client sends a terminate command.
|  | Code listing 1.2: ComServerThread  /**
  * -- A class extended from a Thread; Responsible to service one client --
  */
 class '''ComServerThread''' extends Thread
 {
    private Socket clientSocket = null;
    COM_DATA tDataFromClient;
    COM_DATA tDataToClient; 
    ObjectInputStream oIn;
    ObjectOutputStream oOut;
    /**
     * -- Constructor --
     */
    public ComServerThread( Socket socket )
    {
       super( "ComServerThread" );
       this.clientSocket = socket;
    } // -- End of ComServerThread() constructor --
    /**
     * -- Overrun from the Thread (super) class --
     */
    public void run()
    {
       try {
          // --- Create the Writer; will be used to send data to client ---
          oOut = new ObjectOutputStream( clientSocket.getOutputStream() );
          // --- Create the Reader; will be used to get data from client ---
          oIn  = new ObjectInputStream( clientSocket.getInputStream() );
          // --- Create a new protocol object ---
          ComProtocol comp = new ComProtocol();
          // --- Send something to client to indicate that server is ready ---
          tDataToClient  = '''comp.processInput( null );'''
          '''sendDataToClient'''( tDataToClient, oOut );
          // --- Get the data from the client ---
          while ( true )
          {
             try {
                tDataFromClient = '''getDataFromClient( oIn )''';
                // --- Parse the request and get the reply ---
                tDataToClient = '''comp.processInput( tDataFromClient );'''
                // --- Send data to the Client ---
                '''sendDataToClient'''( tDataToClient, oOut );
             }
             catch ( EOFException e ) {
                System.out.println( "Client Disconnected, Bye, Bye" );
                break;
             }
             // --- See if the Client wanted to terminate the connection ---
             if ( tDataToClient.bExit )
             {
                System.out.println( "Client said Bye. Bye" );
                break;
             }
          }
          // --- Close resources;  This client is gone ---
          comp.Final();
          oOut.close();
          oIn.close();
          clientSocket.close();
       } catch ( IOException e ) {
        e.printStackTrace();
       }
    } // -- End of run() Method --
    /**
     * Get data from Client 
     */
    private static COM_DATA '''getDataFromClient'''( ObjectInputStream oIn ) throws IOException                                                                         
    {
        COM_DATA  tDataFromClient = null;         
        // --- Initialize variables ---
        //   tDataFromClient = new COM_DATA();
        while ( tDataFromClient == null )
        {
           try {
              // --- Read Line Number first --
              tDataFromClient = (COM_DATA) oIn.readObject();
           } catch ( ClassNotFoundException e ) {
               System.out.println( "ClassNotFound" );
           }
        }
        System.out.println( "Get: " + tDataFromClient.comData );
     return tDataFromClient;
    } // --- getDataFromClient() Method --- 
    /**
     * Send data to Client 
     */
    private static void '''sendDataToClient'''( COM_DATA tDataToClient,
                                           ObjectOutputStream  oOut ) throws IOException
    {         
        System.out.println( "Sent: " + tDataToClient.comData );
        oOut.writeObject( tDataToClient );
      return;
    } // -- End of sendDataToClient() Method --
 } // --- End of ComServerThread class ---
 | 
- COM_DATA tDataFromClient
- This variable will contain the data object from the client.
- COM_DATA tDataToClient
- This variable will contain the data object to be sent to the client.
- sendDataToClient
- This method sends the data object to the client.
- getDataFromClient
- This method gets the data object from the client.
- processInput( tDataFromClient )
- This method of the class ComProtocolinterprets the client commands and returns the data object that will be sent back to the client.
Handling the request; implements the communication protocol
- ComProtocol
- This class implements, and encapsulates the communication logic (protocol). The protocol is the following: 
- The client initiate the connection.
- The server accepts it and sends an acknowledgment notifying that it's ready
- The client sends a request
- The server response based on the request
 
- ...
- The client sends a BYErequest
- The server acknowledge the BYErequest and disconnects the socket connection
- The client gets the acknowledgment to the BYE
 
- The client sends a 
- ...
- The client sends a SHUTDOWNrequest
- The server acknowledge the SHUTDOWNrequest and disconnects and also stops listening of other clients.
- The client gets the acknowledgment to the SHUTDOWN
 
- The client sends a 
|  | Code listing 1.3: ComProtocol  class '''ComProtocol'''
 {
  private static final int COM_STATUS_WAITING    = 0; 
  private static final int COM_STATUS_READY_SENT = 1;
  private static final int COM_STATUS_DATA_SENT  = 2;
  private static final int COM_STATUS_WAITING_FOR_TERMINALID = 3;
  private int state = COM_STATUS_WAITING;
  
  // --- Reference to 'BACK-END' module ---  
  private MqTeAccess mqTe;
  ...
    /**
     * Create a protokol object; CAll MQ INI function
     */
    public ComProtocol()
    {
     int    iRet = 0;
        // --- Initialize 'BACK-END' modules  ---
        mqTe. ...
 ...
    }
    /**
     * --- Process the Input and Create the output to the Client ---
     */
    public COM_DATA processInput( COM_DATA theInput )
    {
     COM_DATA theOutput;
        // --- Initialize Variables ---
        theOutput = new COM_DATA();
        // --- Check if the Clients want to disconnect ---
        if ( theInput != null ) 
        {
            if ( theInput.comData.equals('''"!BYE.@"''') )
            {
                // --- The Client wants to terminate; Echo data back to client
                theOutput.comData = "BYE.";
                // --- Mark the communication to be terminated ---
                theOutput.bExit = true;
                // --- Set the internal state to wait for a new client ---
                state = COM_STATUS_WAITING;
                // --- Return Data object to be sent to the client ---
                return theOutput;
            }
            if ( theInput.comData.equals('''"!SHUTDOWN.@"''') )
            {
                // --- The Client wants to terminate; Echo data back to client
                theOutput.comData = "BYE.";
                // --- Mark the communication to be terminated ---
                theOutput.bExit = true;
                // --- Tell the server to stop listening for new clients ---
                ComServer.GL_listening = false;
                // --- Set the internal state to wait for a new client ---
                state = COM_STATUS_WAITING;
                // --- Return Data object to be sent to the client ---
                return theOutput;
            }
        }
        if ( state == COM_STATUS_WAITING )
        {
            // --- Send ready Message to the Client ---
            theOutput.comData = "Ready:";
            // --- Set the internal state ready; and wait for TerminalId ---
            state = COM_STATUS_WAITING_FOR_TERMINALID;
        }
        else if ( state == COM_STATUS_WAITING_FOR_TERMINALID )
        {
         int iRet;
            // --- Get the Terminal ID ---
            sTermId = theInput.comData; 
            // --- Call 'BACK-END' modules ...  ---
            mqTe. ...
 ...
            // --- Send ready Message with the Server Version to the Client ---
            theOutput.comData = "Ready;Server Version 1.0:";
            // --- Set the internal state raedy; and wait for TerminalId ---
            state = COM_STATUS_READY_SENT;
        }
        else if ( state == COM_STATUS_READY_SENT )
        {
         int iRet;
            String sCommand = theInput.comData;
            // --- Call 'BACK-END' modules ...
 ...
            /*
            ** --- Check if we should get Response data ---
            */
            if ( theInput.iRet == COM_DATA.NOWAIT_FOR_RESPONSE ) {
                // -- Set the Output Value ---
                theOutput.iRet = iRet;
                theOutput.comData = "";
            }
            else {
                // --- Call 'BACK-END' modules ---
                mqTe. ...
                // --- Set the Output Value ---
                theOutput.comData    = mqTe.sResponseBuffer; 
                theOutput.iRet       = iRet;
            }
        }
     return theOutput;
    }  // --- End of Method processInput() ---
 } // --- End of ComProtocol Class Definition ---
----
 | 
The Data object that goes through the network
- COM_DATA
- is data structure class that is transmitted through the network. The class contains only data.
|  | Code listing 1.4: COM_DATA  /**
  * COM_DATA data structure 
  */
 public class COM_DATA implements Serializable
 {
  public String  comData;
  public boolean bExit;
  public int     iRet;
    /**
     * --- Constants values can be passed in in iRet to the Server ---
     */
    static final int WAIT_FOR_RESPONSE    = 0;
    static final int NOWAIT_FOR_RESPONSE  = 1;
   /**
    * Initialize the data structure
    */
   public COM_DATA()
   {
      comData     = "";
      bExit       = false;
      iRet        = 0;
   } // -- End of COM_DATA() Constructor --   
   /**
    * Copy over it contents 
    */
   public void copy( COM_DATA tSrc )
   {
      this.comData     = tSrc.comData;
      this.bExit       = tSrc.bExit;
      this.iRet        = tSrc.iRet;
    return;
   } 
 } // -- End of COM_DATA class --
 | 
Create the Client
A client code for a server/service is usually an API that a user application uses to interface to the server. With the help of a client API the user application does not have to know how to connect to the server to get services.
- ComClient
- This class is the client API. The application is using this class to communicate with the server.
The following is the client class for the above server:
|  | Code listing 1.5: ComClient  public class ComClient
 {
  private Socket         comSocket;
  private ObjectOutputStream oOut;
  private ObjectInputStream  oIn;
  private boolean         IsItOpen = false;       
    /**
     * --- Open Socket ---
     */
    public void openCom( String sServerName,
                         int    iPortNumber ) throws UnknownHostException,
                                                              IOException  
    {
       try {
          // --- Open Socket for communication ---
          comSocket = new Socket( sServerName, iPortNumber );     
          // --- Get Stream to write request to the Server ---
          oOut = new ObjectOutputStream( comSocket.getOutputStream() );     
          // --- Get Stream// to read from the Server
          oIn = new ObjectInputStream( comSocket.getInputStream());
          // --- Set internal Member variable that the Communication opened ---
          IsItOpen = true;
       } catch ( java.net.UnknownHostException e ) {
          System.err.println( "(openCom:)Don't know about host: "+sServerName );
          IsItOpen = false;
          throw( e );                                         
       } catch ( java.io.IOException e ) {
          System.err.println("(openCom:)Couldn't get I/O for the connection to: "+ sServerName );
          IsItOpen = false;
          throw( e );         
       }               
    }
    /**
     * --- Check if Socket is open ---
     */
    public boolean isItOpen()
    {
      return IsItOpen;
    }     
    /**
     * --- Get data string from the Server ---
     */
    public void getServerData( COM_DATA tServData ) throws IOException
    {
        // --- Initialize Variables ---
        tServData.comData = "";
        // --- Get the Response from the Server ---              
        try {
           tServData.copy( (COM_DATA) oIn.readObject() );
        }   
        catch ( ClassNotFoundException e ) {
            System.out.println( "Class Not Found" );
        } 
        System.out.println( "Server: " + tServData.comData );
        if ( tServData.comData.equals("BYE.") )
        {
            tServData.bExit = true;
        }        
     return;
    }
    /**
     * --- Send data to the Server ---
     */
    public void sendDataToServer( COM_DATA tServData ) throws IOException
    {
        // --- Send the data string ---
        System.out.println( "Send: " + tServData.comData );
        oOut.writeObject( tServData );
     return;
    } 
    /**
     * --- Close Socket --- 
     */
    public void closeCom() throws IOException
    {
        oOut.close();
        oIn.close();
        comSocket.close();
        IsItOpen = false;
    }    
 }
 | 
- getServerData( COM_DATA tServData )
- This method reads the data from the server and copies the values to tServDataobject.
- sendDataToServer( COM_DATA tServData )
- This method sends the tServDataobject through the network to the server.
- oIn.readObject()
- This method returns the data object sent by the server.
- oOut.writeObject( tServData )
- This method sends the data object to the server.