tokuhirom's Blog

Blocking echo server in Java

ServerSocketChannel を利用した blocking な echo server の実装でまともなのが見当たらなかったので書いた。

System.inheritedChannel() 使うようにもできるようにしたかったから1から書いたという感じ。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.Channel;
import java.nio.channels.ServerSocketChannel;

public class EchoServer {
	public static void main(String[] args) throws IOException {
		final ServerSocket socket = args.length == 1
				? createSocket(Integer.parseInt(args[0]))
				: getInheritedSocket();

		while (true) {
			try (final Socket client = socket.accept()) {
				byte[] buf = new byte[1024];
				while (!client.isClosed()) {
					int read = client.getInputStream().read(buf);
					if (read > 0) {
						client.getOutputStream().write(buf, 0, read);
					} else {
                        client.close();
                    }
				}
				System.out.println("Closed connection.");
			}
		}
	}

	private static ServerSocket createSocket(int port) throws IOException {
		final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		final ServerSocket socket = serverSocketChannel.socket();
		final InetSocketAddress inetSocketAddress = new InetSocketAddress(port);
		socket.setReuseAddress(true);
		socket.bind(inetSocketAddress);
		return socket;
	}

	public static ServerSocket getInheritedSocket() throws IOException {
		final Channel channel = System.inheritedChannel();
		if (channel instanceof ServerSocketChannel) {
			return ((ServerSocketChannel)channel).socket();
		} else {
			throw new IllegalStateException("There is no inherited available server socket: " + channel);
		}
	}
}