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 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:
importjava.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. -- */publicclassComServer{staticbooleanGL_listening=true;/** * -- Main program to start the Server -- */publicstaticvoidmain(String[]args)throwsIOException{ComServersrv=newComServer();srv.listen();}// --- End of Main Method ---/** * -- Server method; Listen for client -- */publicintlisten()throwsIOException{ServerSocketserverSocket=null;intiPortNumber=9090;// --- Open the Server Socket where this should listen ---try{System.out.println("*** Open the listening socket; at:"+iPortNumber+" ***");serverSocket=newServerSocket(iPortNumber);}catch(IOExceptione){System.err.println("Could not listen on port:"+iPortNumber);System.exit(1);}while(GL_listening){ComServerThreadclientServ;// --- Listening for client; If there is a client start a Thread -System.out.println("*** Listen for a Client; at:"+iPortNumber+" ***");clientServ=newComServerThread(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();return0;}// --- 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.
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'''extendsThread{privateSocketclientSocket=null;COM_DATAtDataFromClient;COM_DATAtDataToClient;ObjectInputStreamoIn;ObjectOutputStreamoOut;/** * -- Constructor -- */publicComServerThread(Socketsocket){super("ComServerThread");this.clientSocket=socket;}// -- End of ComServerThread() constructor --/** * -- Overrun from the Thread (super) class -- */publicvoidrun(){try{// --- Create the Writer; will be used to send data to client ---oOut=newObjectOutputStream(clientSocket.getOutputStream());// --- Create the Reader; will be used to get data from client ---oIn=newObjectInputStream(clientSocket.getInputStream());// --- Create a new protocol object ---ComProtocolcomp=newComProtocol();// --- 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(EOFExceptione){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(IOExceptione){e.printStackTrace();}}// -- End of run() Method --/** * Get data from Client */privatestaticCOM_DATA'''getDataFromClient'''(ObjectInputStreamoIn)throwsIOException{COM_DATAtDataFromClient=null;// --- Initialize variables ---// tDataFromClient = new COM_DATA();while(tDataFromClient==null){try{// --- Read Line Number first --tDataFromClient=(COM_DATA)oIn.readObject();}catch(ClassNotFoundExceptione){System.out.println("ClassNotFound");}}System.out.println("Get: "+tDataFromClient.comData);returntDataFromClient;}// --- getDataFromClient() Method --- /** * Send data to Client */privatestaticvoid'''sendDataToClient'''(COM_DATAtDataToClient,ObjectOutputStreamoOut)throwsIOException{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 ComProtocol interprets the client commands and returns the data object that will be sent back to the client.
Handling the request; implements the communication protocol
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 BYE request
The server acknowledge the BYE request and disconnects the socket connection
The client gets the acknowledgment to the BYE
...
The client sends a SHUTDOWN request
The server acknowledge the SHUTDOWN request and disconnects and also stops listening of other clients.
The client gets the acknowledgment to the SHUTDOWN
Code listing 1.3: ComProtocol
class'''ComProtocol'''{privatestaticfinalintCOM_STATUS_WAITING=0;privatestaticfinalintCOM_STATUS_READY_SENT=1;privatestaticfinalintCOM_STATUS_DATA_SENT=2;privatestaticfinalintCOM_STATUS_WAITING_FOR_TERMINALID=3;privateintstate=COM_STATUS_WAITING;// --- Reference to 'BACK-END' module --- privateMqTeAccessmqTe;.../** * Create a protokol object; CAll MQ INI function */publicComProtocol(){intiRet=0;// --- Initialize 'BACK-END' modules ---mqTe.......}/** * --- Process the Input and Create the output to the Client --- */publicCOM_DATAprocessInput(COM_DATAtheInput){COM_DATAtheOutput;// --- Initialize Variables ---theOutput=newCOM_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 clienttheOutput.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 ---returntheOutput;}if(theInput.comData.equals('''"!SHUTDOWN.@"''')){// --- The Client wants to terminate; Echo data back to clienttheOutput.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 ---returntheOutput;}}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;}elseif(state==COM_STATUS_WAITING_FOR_TERMINALID){intiRet;// --- 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;}elseif(state==COM_STATUS_READY_SENT){intiRet;StringsCommand=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;}}returntheOutput;}// --- End of Method processInput() ---}// --- End of ComProtocol Class Definition -------
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 */publicclassCOM_DATAimplementsSerializable{publicStringcomData;publicbooleanbExit;publicintiRet;/** * --- Constants values can be passed in in iRet to the Server --- */staticfinalintWAIT_FOR_RESPONSE=0;staticfinalintNOWAIT_FOR_RESPONSE=1;/** * Initialize the data structure */publicCOM_DATA(){comData="";bExit=false;iRet=0;}// -- End of COM_DATA() Constructor -- /** * Copy over it contents */publicvoidcopy(COM_DATAtSrc){this.comData=tSrc.comData;this.bExit=tSrc.bExit;this.iRet=tSrc.iRet;return;}}// -- End of COM_DATA class --
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
publicclassComClient{privateSocketcomSocket;privateObjectOutputStreamoOut;privateObjectInputStreamoIn;privatebooleanIsItOpen=false;/** * --- Open Socket --- */publicvoidopenCom(StringsServerName,intiPortNumber)throwsUnknownHostException,IOException{try{// --- Open Socket for communication ---comSocket=newSocket(sServerName,iPortNumber);// --- Get Stream to write request to the Server ---oOut=newObjectOutputStream(comSocket.getOutputStream());// --- Get Stream// to read from the ServeroIn=newObjectInputStream(comSocket.getInputStream());// --- Set internal Member variable that the Communication opened ---IsItOpen=true;}catch(java.net.UnknownHostExceptione){System.err.println("(openCom:)Don't know about host: "+sServerName);IsItOpen=false;throw(e);}catch(java.io.IOExceptione){System.err.println("(openCom:)Couldn't get I/O for the connection to: "+sServerName);IsItOpen=false;throw(e);}}/** * --- Check if Socket is open --- */publicbooleanisItOpen(){returnIsItOpen;}/** * --- Get data string from the Server --- */publicvoidgetServerData(COM_DATAtServData)throwsIOException{// --- Initialize Variables ---tServData.comData="";// --- Get the Response from the Server --- try{tServData.copy((COM_DATA)oIn.readObject());}catch(ClassNotFoundExceptione){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 --- */publicvoidsendDataToServer(COM_DATAtServData)throwsIOException{// --- Send the data string ---System.out.println("Send: "+tServData.comData);oOut.writeObject(tServData);return;}/** * --- Close Socket --- */publicvoidcloseCom()throwsIOException{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 tServData object.
sendDataToServer( COM_DATA tServData )
This method sends the tServData object 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.
To do: Add some exercises like the ones in Variables