java.nio.channels.AsynchronousSocketChannel Example
This article introduces the AsynchronousSocketChannel
and its basic usage. This class is available since Java SE 7 as part of Java NIO 2 file API. This article’s example shows the socket channel client sending messages to an AsynchronousServerSocketChannel
server – in a client/server setup.
The example in this article is compiled and run in Windows OS environment. Note that Java SE 7 is required to run the code.
1. Introduction
AsynchronousSocketChannel
an abstract class implements AsynchronousByteChannel
and NetworkChannel
. This class is defined in the java.nio.channels
package.
This is an asynchronous channel for stream-oriented and connecting network sockets.
An AsynchronousSocketChannel
is created by invoking one of the open methods defined by this class. A newly created channel is open but not yet connected. A synchronous socket channel is connected when a connection is made to the socket of an AsynchronousServerSocketChannel
using the connect()
method; once connected, a channel remains connected until it is closed.
Channels of this type are safe for use by multiple concurrent threads. They support concurrent reading and writing, though at most one read operation and one write operation can be outstanding at any time.
2. The Example
The example is a client/server application program. The client uses a AsynchronousSocketChannel
and the server a AsynchronousServerSocketChannel
. The client sends messages and the server receives them. These are two independent programs.
2.1. The AsynchronousServerSocketChannel server
This is the server program.
2.1.1. Open a channel
AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open();
2.1.2. Bind to a socket address
InetSocketAddress hostAddress = new InetSocketAddress("localhost", 3883); serverChannel.bind(hostAddress);
The above code snippet shows binding the server channel’s socket to a local address. This configures the socket to listen for client connections.
2.1.3. Accept a connection
Future acceptResult = serverChannel.accept(); AsynchronousSocketChannel clientChannel = acceptResult.get();
The above code snippet shows the initiation of an asynchronous operation to accept a connection made to this channel’s socket – from a client. The pending result is a Future
object of type AsynchronousSocketChannel
. The future’s get()
method returns the AsynchronousSocketChannel
to the new connection on successful completion.
Note the program waits to accept until the client starts and connects on the port of this server.
2.1.4. Receive messages from client
The connected channel from the previous step reads a sequence of bytes into the given buffer. The read data is the message received from the client. The client program and the code to send messages are explained later in section 2.2. Client.
ByteBuffer buffer = ByteBuffer.allocate(32); Future result = clientChannel.read(buffer);
The received message is printed.
String message = new String(buffer.array()).trim(); System.out.println(message);
The program receives messages from the client – runs in an infinite loop – until the client program sends a message “Bye.” indicating that there are no more messages (it’s the last message). Then the server program terminates.
2.1.5. Close
Close the connection channel and the server channel.
clientChannel.close(); serverChannel.close();
2.2. The AsynchronousSocketChannel client
This is the client program.
2.2.1. Open a channel
AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
2.2.2. Connect to server
Connect this channel to the specified remote server’s address.
InetSocketAddress hostAddress = new InetSocketAddress("localhost", 3883); Future future = client.connect(hostAddress); future.get();
Note the socket address it is to connect is same server’s socket address receiving the connection (as specified in the previous section 2.1. Server). The connect()
method returns a Future
representing the pending result. The future’s get()
method returns a null
on successful connection.
After this step is run, the server is ready to receive the messages sent by this program.
2.3.3. Send messages to server
The client sends three pre-determined messages. The last of three, “Bye.” when sent to the server, the server verifies the message and terminates.
In the following code snippet, the channel’s write()
method initiates an asynchronous write operation. This writes a sequence of bytes to this channel from the given buffer with message data.
String [] messages = new String [] {"Time goes fast.", "What now?", "Bye."}; for (int i = 0; i < messages.length; i++) { byte [] message = new String(messages [i]).getBytes(); ByteBuffer buffer = ByteBuffer.wrap(message); Future result = client.write(buffer);
2.3.4. Close channel
All messages are sent to the server. Close the channel.
client.close();
3. The Code and the Output
The application has two programs – the client and the server. The following are the complete code, the run instructions and the output details.
3.1. Code
3.1.1. Server
ServerExample.java
import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.Future; import java.nio.channels.AsynchronousServerSocketChannel; import java.nio.channels.AsynchronousSocketChannel; import java.util.concurrent.ExecutionException; import java.net.InetSocketAddress; public class ServerExample { public static void main (String [] args) throws Exception { new ServerExample().go(); } private void go() throws IOException, InterruptedException, ExecutionException { AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open(); InetSocketAddress hostAddress = new InetSocketAddress("localhost", 3883); serverChannel.bind(hostAddress); System.out.println("Server channel bound to port: " + hostAddress.getPort()); System.out.println("Waiting for client to connect... "); Future acceptResult = serverChannel.accept(); AsynchronousSocketChannel clientChannel = acceptResult.get(); System.out.println("Messages from client: "); if ((clientChannel != null) && (clientChannel.isOpen())) { while (true) { ByteBuffer buffer = ByteBuffer.allocate(32); Future result = clientChannel.read(buffer); while (! result.isDone()) { // do nothing } buffer.flip(); String message = new String(buffer.array()).trim(); System.out.println(message); if (message.equals("Bye.")) { break; // while loop } buffer.clear(); } // while() clientChannel.close(); } // end-if serverChannel.close(); } }
3.1.2. Client
ClientExample.java
import java.io.IOException; import java.nio.ByteBuffer; import java.util.concurrent.Future; import java.nio.channels.AsynchronousSocketChannel; import java.util.concurrent.ExecutionException; import java.net.InetSocketAddress; public class ClientExample { public static void main (String [] args) throws Exception { new ClientExample().go(); } private void go() throws IOException, InterruptedException, ExecutionException { AsynchronousSocketChannel client = AsynchronousSocketChannel.open(); InetSocketAddress hostAddress = new InetSocketAddress("localhost", 3883); Future future = client.connect(hostAddress); future.get(); // returns null System.out.println("Client is started: " + client.isOpen()); System.out.println("Sending messages to server: "); String [] messages = new String [] {"Time goes fast.", "What now?", "Bye."}; for (int i = 0; i < messages.length; i++) { byte [] message = new String(messages [i]).getBytes(); ByteBuffer buffer = ByteBuffer.wrap(message); Future result = client.write(buffer); while (! result.isDone()) { System.out.println("... "); } System.out.println(messages [i]); buffer.clear(); Thread.sleep(3000); } // for client.close(); } }
3.2. The output
The two programs are to be started independently. Note the server program is started first.
3.2.1. Start the server
Start the server program in a new DOS window. The following is the output:
> java ServerExample Server channel bound to port: 3883 Waiting for client to connect...
From the output note the server port 3883. The program waits to accept, until the client connects.
3.2.2. Start the client
Start the client program in another DOS window. The following is the output:
> java ClientExample Client is started: true Sending messages to server: Time goes fast. ... What now? ... Bye.
From the output, note the client is started. This connects to the server’s port 3883. After connecting, three messages are sent to the server, one at a time.
3.2.3. Check messages on server
The following output shows the server receiving the three messages sent by the client, one at a time.
Server channel bound to port: 3883 Waiting for client to connect... Messages from client: Time goes fast. What now? Bye.
4. Download Java Source Code
This was an example of java.nio.channels.AsynchronousSocketChannel
You can download the full source code of this example here: AsynchronousSocketChannelExamples.zip