◎위챗 : speedseoul
http://en.wikibooks.org/wiki/Java_Programming/Client_Server
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 could simply communicate.
In this page there is an example for socket connection.
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 request. When a request arrives, it starts a new thread to service the request. See the following example:
Code listing 1.1: ComServerimport 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 --- |
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 --- |
ComProtocol
interprets the client commands and returns the data object that will be sent back to the client.BYE
requestBYE
request and disconnects the socket connectionBYE
SHUTDOWN
requestSHUTDOWN
request and disconnects and also stops listening of other clients.SHUTDOWN
Code listing 1.3: ComProtocolclass '''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 comunication 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 comunication 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 --- ---- |
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 -- |
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.
The following is the client class for the above server:
Code listing 1.5: ComClientpublic 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; } } |
tServData
object.tServData
object through the network to the server.