Previous | Next | Trail Map | Custom Networking and Security | All about Sockets


Reading from and Writing to a Socket

The following program is a simple example of how to establish a connection from a client program to a server program through a socket. The Socket class in the java.net package is a platform-independent implementation of the client end of a two-way communication link between a client program and a server program. Typically, the Socket class sits on top of a platform-dependent implementation hiding the details of any particular system from your Java program. Thus, when working with Sockets, you should always use the java.net.Socket class and bypass the underlying system-dependent functions. In this way, your Java programs will remain system neutral.

This client program, EchoTest, connects to the standard Echo server (on port 7) via a socket. The client is both reading from and writing to the socket. EchoTest sends all text typed into its standard input by the user to the Echo server by writing the text to the socket. The server echos all input it receives from the client back through the socket to the client. The client program reads the data passed back to it from the server via the socket and displays all the data it receives back from the server.

import java.io.*;
import java.net.*;

public class EchoTest {
    public static void main(String[] args) {
        try {
            Socket echoSocket = new Socket("taranis", 7);
            OutputStream os = echoSocket.getOutputStream();
            DataInputStream is = new DataInputStream(echoSocket.getInputStream());

            int c;
            String responseLine;

            while ((c = System.in.read()) != -1) {
                os.write((byte)c);
                if (c == '\n') {
                    os.flush();
                    responseLine = is.readLine();
                    System.out.println("echo: " + responseLine);
                }
            }

            os.close();
            is.close();
            echoSocket.close();
        } catch (Exception e) {
            System.err.println("Exception:  " + e);
        }
    }
}
Let's walk through the program and investigate the interesting bits.

The first three lines of code within the try block of the main() method are critical--they establish the socket connection between the client and the server and open an input stream and an output stream on the socket.

Socket echoSocket = new Socket("taranis", 7);
OutputStream os = echoSocket.getOutputStream();
DataInputStream is = new DataInputStream(echoSocket.getInputStream());
This first line in this sequence creates a new Socket object and names it echoSocket. The Socket constructor used here (there are three others) requires the name of the machine and the port number that you want to connect to. The example program uses the hostname taranis which is the name of a (hypothetical) machine on our local network. When you type in and run this program on your machine, you will want to change this to the name of a machine on your network. The second argument is the port number. Port number 7 is the port that the Echo server listens to.

The second line in the code snippet above opens an output stream on the socket, and the third line opens an input stream on the socket. Now, EchoTest merely needs to write to the output stream and read from the input stream to communicate through the socket to the server. The rest of the program achieves this. If you are not yet familiar with input and output streams, see Input and Output Streams(in the Writing Java Programs trail).

The next section of code reads from EchoTest's standard input stream (where the user can type in data) one character at a time. EchoTest writes each character individually to the output stream connected to the socket. When the user types in a carriage return (`\n`) EchoTest flushes the output stream, thereby sending an entire line typed in by the user at once.

int c;
String responseLine;

while ((c = System.in.read()) != -1) {
    os.write((byte)c);
    if (c == '\n') {
        os.flush();
        responseLine = is.readLine();
        System.out.println("echo: " + responseLine);
    }
}   
Next EchoTest reads a line of information from the input stream connected to the socket. The readLine() method blocks until the server echos the information back to EchoTest. When readline() returns EchoTest prints the information to standard out.

This loop continues--EchoTest reads input from the user, sends it to the Echo server, gets a response from the server and displays it--until the user types an end-of-input character.

When the user types an end-of-input character, the while terminates and the program continues on executing the next three lines of code:

os.close();
is.close();
echoSocket.close();
These lines of code fall into the category of housekeeping. A well-behaved program always cleans up after itself and this program is no different. These three lines of code close the input and output stream connected to the socket, and close the socket connection to the server. The order here is important--you should close any streams connected to a socket before you close the socket itself.

This client program is straightforward and simple because the Echo server implements a simple protocol. The client sends text to the server, the server echos it back. When your client programs are talking to a more complicated server such as an http server, your client program will also be more complicated. However, the basics are much the same as they are in this program:

  1. open a socket
  2. open an input and output stream to the socket
  3. read from and write to the socket according to the server's protocol
  4. clean up
Only step 3 differs from client to client depending on the server that it's talking to. The other steps remain largely the same.

A Note about Exception Handling

The EchoTest program violates a programming convention in regard to exception handling. The EchoTest program uses a single, general catch clause to catch all possible exceptions that occur within its try block. In general, programs should not do this, but rather, catch different types of exceptions in different clauses and handle them separately. For information about exception handling, refer to Handling Errors using Exceptions(in the Writing Java Programs trail).

See also

java.net.Socket


Previous | Next | Trail Map | Custom Networking and Security | All about Sockets