Example code: JavaSockets.zip

This code is an Eclipse project, and you can also build and run from the command line. To build, run the command ant. To run one of the example programs, use one of the following commands:

./run.sh Server port
./run.sh Client hostname port message
./run.sh Server2 port

Note that you’ll need to make run.sh executable:

chmod a+x run.sh

Socket programming in Java

Socket programming Java is much easier than in C.

Basic socket programming

java.net.ServerSocket — a server socket which may be used to accept connections. Usually, the constructor is passed a port number. Optionally, you can specify a specific network to listen on (along with the port) if you only want to accept connections from particular networks. Call the accept() method to wait for an incoming connection (which is returned as a Socket, see below).

java.net.Socket — a general two-way communication socket. Call the getInputStream() and getOutputStream() methods to get InputStream and OutputStream objects receiving data from and sending data to the remote process. A connection to a remote server can be established by passing a hostname and port number to the constructor.

Example programs:

Concurrency issues

The concurrency issues with Java sockets are similar to the ones for programming with C sockets.

One basic issue is that if the server is single-threaded in the obvious way, only one client at a time can connect. A straightforward solution to this problem is to use threads, such that each client connection is handled by a single thread.

Another important issue is that the accept() method of ServerSocket is a blocking method, and will suspend the calling thread indefinitely if there are no incoming client connection requests. This can make it difficult for the server to shut down gracefully. The solution to this problem is similar to C: make the server socket nonblocking, and use a timed wait to accept incoming connections, giving the server process opportunities to do other processing (such as checking whether a shutdown was requested) at regular intervals.

Nonblocking I/O and timed waits in Java require the use of the java.nio framework, often referred to as simply “nio”. The essential abstraction in nio is the “channel”, which you can think of as being equivalent to a file descriptor: it names an I/O resource such as an input stream, output stream, socket, or server socket.

java.nio.channels.ServerSocketChannel — A channel class which is the nio equivalent of java.net.ServerSocket. Created with a call to ServerSocketChannel.open(). It must be bound to an address and port using by calling the bind method. The configureBlocking method can be used to set the server socket to nonblocking.

java.nio.channels.SocketChannel — A channel which refers to a two-way communications socket. You can call the sock() method to get a reference to the underlying java.net.Socket object.

java.nio.channels.Selector — A set of SelectionKeys, where each SelectionKey monitors one channel (such as a ServerSocketChannel). Allows the program to wait for one or more channels to become ready, such as a server socket channel becoming ready to accept a connection. Is analogous to fd_set in C. Call the select method to wait for one or more channels to become ready: a timeout argument may be provided to cause select to return if no activity occurs before the timeout.

java.nio.channel.SelectionKey — An object that represents the status of a monitored channel. When the select method of a Selector returns, the program can iterate through the set of SelectionKeys that are ready for I/O. Note that keys must be removed from the Selector’s ready set, otherwise they may appear to be ready even if they aren’t.

Example program: