Java Sockets

  1. What are TCP Sockets?
  2. Java Servers
  3. Java Clients
  4. Complete Java Client-Server Echo Program
  5. Exercise

What are TCP sockets?

A TCP socket is defined as an endpoint for communication. A socket consists of the pair <IP Address,Port>. For our purposes, a port will be defined as an integer number between 1024 and 65535. This is because all port numbers smaller than 1024 are considered well-known -- for example, telnet uses port 23, http uses 80, ftp uses 21, and so on. On Unix machines, the file /etc/services contains a list of services provided by that machine, along with their well-known ports

A TCP connection consists of a pair of sockets. Sockets are distinguished by client and server sockets. A server listens on a port, waiting for incoming requests from clients.

For example, a web server listens at port 80 for incoming request from clients (web browsers). When a client wishes to make a connection with a server socket, the client is assigned a port from the local host. Suppose that client X (at IP address 146.86.3.15) wishes to browse a web page on the server 146.86.5.20. If the port the local host assigned client X is port 12345, the connection between the client and the server is uniquely identified by the socket pair

            <146.86.3.15 : 12345, 146.86.5.20 : 80>


Java Servers

This section walks you through the code that implements a simple echo server program. The server program begins by creating a new ServerSocket object to listen on a specific port. When writing a server, one should choose a port that is not already dedicated to some other service. In the code below, the server listens omn port 1234:


    try {
        serverSocket = new ServerSocket(1234);
    } catch (IOException e) {
        System.out.println("Could not listen on port: 1234");
        System.exit(-1);
    }
ServerSocket is a java.net class, so be sure to say import java.net.*; at the beginning of your file. If the server successfully binds to its port, then the ServerSocket object is successfully created and the server continues to the next step-- accepting a connection from a client:

    Socket clientSocket = null;
    try {
        clientSocket = serverSocket.accept();
    } catch (IOException e) {
        System.out.println("Accept failed: 1234");
        System.exit(-1);
    }
The accept method waits until a client starts up and requests a connection on the host and port (1234 of this server. When a connection is requested and successfully established, the accept method returns a new Socket object which is bound to the same local port and has its remote address and remote port set to that of the client. The server can communicate with the client over this new Socket and continue to listen for client connection requests on the original ServerSocket.

After the server successfully establishes a connection with a client, it can communicate with the client using code similar to this:


    PrintWriter out = new PrintWriter(
                          clientSocket.getOutputStream(), true);
    BufferedReader in = new BufferedReader(
                        new InputStreamReader(
                            clientSocket.getInputStream()));
    String inputLine, outputLine;

    while ((inputLine = in.readLine()) != null) {	
        outputLine = "Server: " + inputline;
        out.println(outputLine);
        if outputLine.equals("bye"))
            break;
    }
In the while loop, for as long as the client and server still have something to say to each other, the server reads from and writes to the socket, sending messages back and forth between the client and the server.

Well-behaved servers should clean up by closing all of the input and output streams, the client socket, and the server socket:


    out.close();
    in.close();
    clientSocket.close();
    serverSocket.close();

Java Clients

This section walks you through the code that implements the client program corresponding to the server above. When you start the client program, the server should already be running and listening to the port, waiting for a client to request a connection. So, the first thing the client program does is to open a socket that is connected to the server running on the hostname and port specified:


    mySocket = new Socket("localhost", 1234);
    out = new PrintWriter(mySocket.getOutputStream(), true);
    in = new BufferedReader(new InputStreamReader(
                                mySocket.getInputStream()));
A connection to the server is attempted through the instantiation of the Socket class. The client attempts to contact the server at localhost through port 1234 - the same port where the server is listening. localhost corresponds to the default local computer IP address of 127.0.0.1. This way, both the server and the client will be running on the same computer. To be able to access the server (running on tanner, for instance) from any computer, use tanner.csc.villanova.edu in place of localhost.

Next comes the while loop that implements the communication between the client and the server. The client speaks first by writing into the output stream attached to the socket.


    while (1) {
        fromUser = System.in.readLine();
        if(fromUser == null)
            break;
        out.println(fromUser);
        fromServer = in.readLine();        
        System.out.println(fromServer);
        if (fromServer.equals("bye"))
            break;
    }
This client not only gets the input and output stream from the socket, but it also gets the input stream from System.in. This allows it to read from the standard input (i.e. keyboard). Whenever the user enters a line on the keyboard, the client reads it and writes it to the socket. The client then reads from the socket, awaiting the echo back from the server. The communication ends when the end-of file (CTRL-D) is encountered, or the user says "bye".

In the interest of good housekeeping, the client should also closes its input and output streams and the socket:


    out.close();
    in.close();
    mySocket.close();

Complete Java Client-Server Echo Program

The server in this program listens to a port specified as an integer argument. Once a client sends a "request" to the server, everything the client enters, the server echoes back. The client signals the end of his message with a period or end of file (hit ^D).

The Java echo client:     EchoClient.java

The Java echo server:     EchoServer.java

Everything the server receives from the client, it sends back.


Testing the client-server echo program

Copy the code for the server (EchoServer.java) and the code for the client (EchoClient.java) either on your local machine or on tanner. In a (Command Prompt ) window, compile the two programs using the java compiler javac:
javac EchoServer.java
javac EchoClient.java
To test the server, use the
port number assigned to you. Start the server by typing at the command prompt
java EchoServer <Port Number>

In a separate Command Prompt window, start the echo client. You need to specify the computer on which the server is running (localhost, if the server is on the same machine as the client, or tanner.csc.villanova.edu, or whatever machine the server is running on) and the port number on which it is listening.

java EchoClient localhost <Port Number>

Now, everything you enter on that window will be echoed back to you. The client breaks the connection by entering "bye" on a line by itself.