- 2.1. ソケット
- 2.2. InetAddressクラス
- 2.3. SocketAddress/InetSocketAddressクラス
- 2.4. Socketクラス
- 2.5. TCPサーバプログラム
- 2.6. TCPクライアントプログラム
- 2.7. プログラムの実行
2.6. TCPクライアントプログラム
次にクライアントアプリケーションを示します。キーボードからの入力をサーバプログラムに送信し、送り返されてきた文字列をコンソールに出力するプログラムです。空行の入力があった時、接続を切断して終了するようにします。
リスト EchoClient.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 EchoClient { public static final int ECHO_PORT = 10007; public static void main(String args[]) { Socket socket = null; try { socket = new Socket(args[0], ECHO_PORT); System.out.println("接続しました" + socket.getRemoteSocketAddress()); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in)); String input; while ( (input = keyIn.readLine()).length() > 0 ) { out.println(input); String line = in.readLine(); if (line != null) { System.out.println(line); } else { break; } } } catch (IOException e) { e.printStackTrace(); } finally { try { if (socket != null) { socket.close(); } } catch (IOException e) {} System.out.println("切断されました " + socket.getRemoteSocketAddress()); } } }
15行目で新しいソケットを作成しています。ここではString型のホスト名を指定するコンストラクタを利用しています。接続先ホスト名はコマンドライン引数で指定したものとし、ポート番号は10007としています。
socket = new Socket(args[0], ECHO_PORT);
16〜17行目では、接続されたソケットの接続先情報を表示しています。getRemoteSocketAddressメソッドは接続先のSocketAddressを返すメソッドです。
System.out.println("接続しました" + socket.getRemoteSocketAddress());
18〜20行目では、ソケットに対して入出力を行うためのReader/Writerおよび、キーボードからの入力を受け取るためのReaderを作成しています。
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true); BufferedReader keyIn = new BufferedReader(new InputStreamReader(System.in));
21〜30行目で、サーバーとの通信処理を行っています。キーボードから入力された文字列をサーバに対して送信し、送り返されてきた文字列を表示します。ループによって空行が入力されるまで処理を繰り返しています。
String input; while ( (input = keyIn.readLine()).length() > 0 ) { out.println(input); String line = in.readLine(); if (line != null) { System.out.println(line); } else { break; } }
サーバの終了によってソケットの接続が切れた場合など、readLineメソッドの戻り値がnullとなることがあるので、そのときもループから抜けるようにしています。ソケット切断時は例外が発生する場合もあるので、例外処理も正しく記述しなければいけません。(ソケット切断時の動作はOSによって異なります。プロセスを強制終了した時、SolarisやLinuxではTCPコネクションの終了処理を正しく行うのに対し、WindowsではTCPコネクションの終了処理を行わないためです。)
33〜41行目のfinally節では、確実にソケットを切断するための処理を記述しています。ソケットは明示的に閉じる習慣をつけておきましょう。
} finally { try { if (socket != null) { socket.close(); } } catch (IOException e) {} System.out.println("切断されました " + socket.getRemoteSocketAddress()); }