Java.next -- Four languages that represent the future of Java
Blogger Stuart Halloway has begun a series of posts on trends that point to the future of the Java platform. In his first post, he compares Clojure, Groovy, JRuby, and Scala -- four wildly different languages that nonetheless all play together in the JRE. Find out what unites these languages and what they can tell us about the future of Java-based development ...

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

Sockets programming in Java: A tutorial

Writing your own client/server applications can be done seamlessly using Java

Page 2 of 4

Now, you might ask what protocol you should use -- UDP or TCP? This depends on the client/server application you are writing. The following discussion shows the differences between the UDP and TCP protocols; this might help you decide which protocol you should use.

In UDP, as you have read above, every time you send a datagram, you have to send the local descriptor and the socket address of the receiving socket along with it. Since TCP is a connection-oriented protocol, on the other hand, a connection must be established before communications between the pair of sockets start. So there is a connection setup time in TCP.

In UDP, there is a size limit of 64 kilobytes on datagrams you can send to a specified location, while in TCP there is no limit. Once a connection is established, the pair of sockets behaves like streams: All available data are read immediately in the same order in which they are received.

UDP is an unreliable protocol -- there is no guarantee that the datagrams you have sent will be received in the same order by the receiving socket. On the other hand, TCP is a reliable protocol; it is guaranteed that the packets you send will be received in the order in which they were sent.

In short, TCP is useful for implementing network services -- such as remote login (rlogin, telnet) and file transfer (FTP) -- which require data of indefinite length to be transferred. UDP is less complex and incurs fewer overheads. It is often used in implementing client/server applications in distributed systems built over local area networks.

Programming sockets in Java

In this section we will answer the most frequently asked questions about programming sockets in Java. Then we will show some examples of how to write client and server applications.

Note: In this tutorial we will show how to program sockets in Java using the TCP/IP protocol only since it is more widely used than UDP/IP. Also: All the classes related to sockets are in the java.net package, so make sure to import that package when you program sockets.

How do I open a socket?

If you are programming a client, then you would open a socket like this:

    Socket MyClient;
    MyClient = new Socket("Machine name", PortNumber);


Where Machine name is the machine you are trying to open a connection to, and PortNumber is the port (a number) on which the server you are trying to connect to is running. When selecting a port number, you should note that port numbers between 0 and 1,023 are reserved for privileged users (that is, super user or root). These port numbers are reserved for standard services, such as email, FTP, and HTTP. When selecting a port number for your server, select one that is greater than 1,023!

In the example above, we didn't make use of exception handling, however, it is a good idea to handle exceptions. (From now on, all our code will handle exceptions!) The above can be written as:

    Socket MyClient;
    try {
           MyClient = new Socket("Machine name", PortNumber);
    }
    catch (IOException e) {
        System.out.println(e);
    }


If you are programming a server, then this is how you open a socket:

    ServerSocket MyService;
    try {
       MyServerice = new ServerSocket(PortNumber);
        }
        catch (IOException e) {
           System.out.println(e);
        }


When implementing a server you also need to create a socket object from the ServerSocket in order to listen for and accept connections from clients.

    Socket clientSocket = null;
    try {
       serviceSocket = MyService.accept();
        }
    catch (IOException e) {
       System.out.println(e);
    }


How do I create an input stream?

On the client side, you can use the DataInputStream class to create an input stream to receive response from the server:

    DataInputStream input;
    try {
       input = new DataInputStream(MyClient.getInputStream());
    }
    catch (IOException e) {
       System.out.println(e);
    }


The class DataInputStream allows you to read lines of text and Java primitive data types in a portable way. It has methods such as read, readChar, readInt, readDouble, and readLine,. Use whichever function you think suits your needs depending on the type of data that you receive from the server.

On the server side, you can use DataInputStream to receive input from the client:

    DataInputStream input;
    try {
       input = new DataInputStream(serviceSocket.getInputStream());
    }
    catch (IOException e) {
       System.out.println(e);
    }


How do I create an output stream?

On the client side, you can create an output stream to send information to the server socket using the class PrintStream or DataOutputStream of java.io:

    PrintStream output;
    try {
       output = new PrintStream(MyClient.getOutputStream());
    }
    catch (IOException e) {
       System.out.println(e);
    }


The class PrintStream has methods for displaying textual representation of Java primitive data types. Its Write and println methods are important here. Also, you may want to use the DataOutputStream:

    DataOutputStream output;
    try {
       output = new DataOutputStream(MyClient.getOutputStream());
    }
    catch (IOException e) {
       System.out.println(e);
    }


The class DataOutputStream allows you to write Java primitive data types; many of its methods write a single Java primitive type to the output stream. The method writeBytes is a useful one.

On the server side, you can use the class PrintStream to send information to the client.

    PrintStream output;
    try {
       output = new PrintStream(serviceSocket.getOutputStream());
    }
    catch (IOException e) {
       System.out.println(e);
    }


Note: You can use the class DataOutputStream as mentioned above.

How do I close sockets?

You should always close the output and input stream before you close the socket.

On the client side:

    try {
           output.close();
           input.close();
       MyClient.close();
    } 
    catch (IOException e) {
       System.out.println(e);
    }


On the server side:

    try {
       output.close();
       input.close();
       serviceSocket.close();
       MyService.close();
    } 
    catch (IOException e) {
       System.out.println(e);
    }


Examples

In this section we will write two applications: a simple SMTP (simple mail transfer protocol) client, and a simple echo server.

1. SMTP client

Let's write an SMTP (simple mail transfer protocol) client -- one so simple that we have all the data encapsulated within the program. You may change the code around to suit your needs. An interesting modification would be to change it so that you accept the data from the command-line argument and also get the input (the body of the message) from standard input. Try to modify it so that it behaves the same as the mail program that comes with Unix.

Resources