3. サーバソケット
- 3.1. サーバソケット
- 3.2. 複数の通信を受け付けるサーバ
この節ではソケットを利用したサーバアプリケーションの作成方法を解説します。マルチスレッドで複数の接続を処理できるサーバの作成方法についても解説します。
3.1. サーバソケット
前節では、新しいSocketインスタンスを作成しサーバに接続するクライアントアプリケーションを作成しました。それでは、クライアントからの接続を受け付けるサーバはどのようにして実現するのでしょうか。接続を受け付けるためにはServerSocketクラスを用います。
クライアントのアプリケーションは、サーバに接続したいときにいつでも接続できます。接続先を指定してSocketのインスタンスを作成すれば、ただちにサーバへの接続が完了していました。しかし、サーバ側は、クライアントがいつ接続を要求してくるかわかりません。そのため、クライアントが接続してくるのをずっと待っていなければいけません。
接続を受け付けられる状態で待機するには、acceptメソッドを用います。acceptメソッドを呼び出すと、ServerSocketは接続待ちの状態となり、クライアントが接続してくるまでプログラムはそれ以上先に進みません。クライアントが接続してくると、acceptメソッドは、そのクライアントと接続されたソケットを返して終了します。サーバアプリケーションはここで取得したソケットを利用してクライアントとの通信処理を行います。
それでは、前節で利用したEchoServerクラスのソースファイルを見てみましょう。
リスト EchoServer.java
import java.net.Socket; import java.net.ServerSocket; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.IOException; public class EchoServer { public static final int ECHO_PORT = 10007; public static void main(String args[]) { ServerSocket serverSocket = null; Socket socket = null; try { serverSocket = new ServerSocket(ECHO_PORT); System.out.println("EchoServerが起動しました(port=" + serverSocket.getLocalPort() + ")"); socket = serverSocket.accept(); System.out.println("接続されました " + socket.getRemoteSocketAddress() ); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); String line; while ( (line = in.readLine()) != null ) { System.out.println("受信: " + line); out.println(line); System.out.println("送信: " + line); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (socket != null) { socket.close(); } } catch (IOException e) {} try { if (serverSocket != null) { serverSocket.close(); } } catch (IOException e) {} } } }
16行目で、待ち受けポートを指定して新しいサーバソケットを生成しています。
serverSocket = new ServerSocket(ECHO_PORT);
19行目でacceptメソッドを呼び出し、クライアントからの接続待機状態に入ります。クライアントからの接続要求があると、socketにはクライアントとの通信に利用できるSocketのインスタンスが代入されます。
socket = serverSocket.accept();
Socketが利用できるようになると、あとはクライアントアプリケーションと同じように入出力ストリームを取得して通信処理を行います。25〜29行のループで通信処理を記述しています。このサーバはクライアントから送られてきた文字列をそのまま送り返すだけの処理を行います。
while ( (line = in.readLine()) != null ) { System.out.println("受信: " + line); out.println(line); System.out.println("送信: " + line); }