Section 15.7. ClientServer Communication via Sockets


[Page 732 (continued)]

15.7. Client/Server Communication via Sockets

As we said earlier, many networking applications are based on the client/server model. According to this model, a task is viewed as a service that can be requested by clients and handled by servers. In this section, we develop a simple client/server framework based on a socket connection between the client and the server.

A socket is a simple communication channel through which two programs communicate over a network. A socket supports two-way communication between a client and a server, using a well-established protocol. The protocol simply prescribes rules and behavior that both the server and client must follow in order to establish two-way communication.

According to this protocol, a server program creates a socket at a certain port and waits until a client requests a connection. A port is a specific address or entry point on the host computer, which typically has hundreds of potential ports. It is usually represented as a simple integer value. For example, the standard port for an HTTP (Web) server is 80. Once the connection is established, the server creates input and output streams to the socket and begins sending messages to and receiving messages from the client. Either the client or the server can close the connection, but it is usually done by the client.

Sockets and ports


Debugging Tip: Reserved Port Numbers

Port numbers below 1024 are reserved for system use and should not be used by an application program.


To clarify this protocol, think of some service performed by a human using a telephone connection. The "server" waits for the phone to ring. When it rings, the server picks it up and begins communicating with the client. A socket, combined with input and output streams, is something like a two-way phone connection.

Client/server protocol


From the client's side, the protocol goes as follows: The client creates a socket and attempts to make a connection to the server. The client has to know the server's URL and the port at which the service exists. Once a connection has been established, the client creates input and output streams to the socket and begins exchanging messages with the server. The client can close the connection when the service is completed.


[Page 733]

Think again of the telephone analogy. A human client picks up the phone and dials the number of a particular service. This is analogous to the client program creating a socket and making a connection to a server. Once the service agent answers the phone, two-way communication between the client and the server can begin.

Figure 15.22 provides a view of the client/server connection. Note that a socket has two channels. Once a connection has been established between a client and a server, a single two-way channel exists between them. The client's output stream is connected to the server's input stream. The server's output stream is connected to the client's input stream.

Figure 15.22. A socket is a two-channel communication link.


Sockets and channels


Java Programming Tip: Socket Streams

A socket has two streams, one for input and one for output.


15.7.1. The Server Protocol

Let's now see how a client/server application would be coded in Java. The template in Figure 15.23 shows the code that is necessary on the server side. The first step the server takes is to create a ServerSocket. The first argument to the ServerSocket() method is the port at which the service will reside. The second argument specifies the number of clients that can be backlogged, waiting on the server, before a client will be refused service. If more than one client at a time requests service, Java will establish and manage a waiting list, turning away clients when the list is full.

Figure 15.23. Template for the server protocol.

Socket socket;                           // Reference to the socket ServerSocket port;                       // The port where the server will listen try {     port = new ServerSocket(10001, 5);  // Create a port     socket = port.accept();             // Wait for client to call                                         // Communicate with the client     socket.close(); } catch (IOException e) {     e.printStackTrace(); } 


[Page 734]

The next step is to wait for a client request. The accept() method will block until a connection is established. The Java system is responsible for waking the server when a client request is received.

Waiting for client requests


Once a connection is established, the server can begin communicating with the client. As we have suggested, a socket connection is like a two-way telephone conversation. Client and server can "talk" back and forth to each other. The details of this step are not shown here. As we will see, the two-way conversation is managed by connecting both an input and an output stream to the socket.

Once the conversation between client and server is finishedonce the server has delivered the requested servicethe server can close the connection by calling close(). Thus, there are four steps involved on the server side:

  • Create a ServerSocket and establish a port number.

  • Listen for and accept a connection from a client.

  • Converse with the client.

  • Close the socket.

What distinguishes the server from the client is that the server establishes the port and accepts the connection.

15.7.2. The Client Protocol

The client protocol (Fig. 15.24) is just as easy to implement. Indeed, on the client side there are only three steps involved. The first step is to request a connection to the server. This is done in the Socket() constructor by supplying the server's URL and port number. Once the connection is established, the client can carry out two-way communication with the server. This step is not shown here. Finally, when the client is finished, it can simply close() the connection. Thus, from the client side, the protocol involves just three steps:

  • Open a socket connection to the server, given its address.

  • Converse with the server.

  • Close the connection.

Figure 15.24. Template for the client protocol.

Socket connection;                         // Reference to the socket try {                                      // Request a connection    connection = new Socket("java.cs.trincoll.edu", 10001);                                            // Carry on a two-way communication      connection.close();                   // Close the socket } catch (IOException e ) {      e.printStackTrace(); } 

Initiating a request


What distinguishes the client from the server is that the client initiates the two-way connection by requesting the service.


[Page 735]

15.7.3. A Two-Way Stream Connection

Now that we have seen how to establish a socket connection between a client and server, let's look at the actual two-way communication that takes place. Because this part of the process will be exactly the same for both client and server, we develop a single set of methods, writeToSocket() and readFromSocket(), that may be called by either.

The writeToSocket() method takes two parameters, the Socket and a String, which will be sent to the process on the other end of the socket:

protected void writeToSocket(Socket sock, String str)throws IOException {     oStream = sock.getOutputStream();     for (int k = 0; k < str.length(); k++)         oStream.write(str.charAt(k)); } // writeToSocket() 


Output routine


If writeToSocket() is called by the server, then the string will be sent to the client. If it is called by the client, the string will be sent to the server.

The method is declared protected because we will define it in a superclass so that it can be inherited and used by both the client and server classes. Note also that the method declares that it throws an IOException. There is no way to fix an IOException, so we will just let this exception be handled elsewhere, rather than handle it within the method.

Protected methods


In order to write to a socket we need only get the socket's OutputStream and then write to it. For this example, oStream is an instance variable of the client/server superclass. We use the getOutputStream() method of the Socket class to get a reference to the socket's output stream. Note that we are not creating a new output stream here. We are just getting a reference to an existing stream, which was created when the socket connection was accepted. Note also that we do not close the output stream before exiting the method. This is important. If you close the stream, you will lose the ability to communicate through the socket.

Java Language Rule: Socket Streams

When a socket is created, it automatically creates its own streams. To use one you just need to get a reference to it.


Debugging Tip: Socket Streams

After writing to or reading from a socket I/O stream, do not close the stream. That would make the socket unusable for subsequent I/O.


Given the reference to the socket's output stream, we simply write each character of the string using the write() method of the OutputStream class. This method writes a single byte. Therefore, the input stream on the other side of the socket must read bytes and convert them back into characters.

Effective Design: Designing a Protocol

In designing two-way communication between a client and a server, you are designing a protocol that each side must use. Failure to design and implement a clear protocol will cause the communication to break down.



[Page 736]

The readFromSocket() method takes a Socket parameter and returns a String:

protected String readFromSocket(Socket sock)throws IOException {     iStream = sock.getInputStream();     String str="";     char c;     while (  ( c = (char) iStream.read() ) != '\n')         str = str + c + "";     return str; } 


Input routine


It uses the getInputStream() method of the Socket class to obtain a reference to the socket's input stream, which has already been created. So here again it is important not to close the stream in this method. A socket's input and output streams will be closed automatically when the socket connection itself is closed.

The read() method of the InputStream class reads a single byte at a time from the input stream until an end-of-line character is received. For this particular application, the client and server will both read and write one line of characters at a time. Note the use of the cast operator (char) in the read() statement. Because bytes are being read, they must be converted to char before they can be compared to the end-of-line character or concatenated to the String. When the read loop encounters an end-of-line character, it terminates and returns the String that was input.

Debugging Tip: Bytes and Chars

It is a syntax error to compare a byte and a char. One must be converted to the other using an explicit cast operator.





Java, Java, Java(c) Object-Orienting Problem Solving
Java, Java, Java, Object-Oriented Problem Solving (3rd Edition)
ISBN: 0131474340
EAN: 2147483647
Year: 2005
Pages: 275

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