ソケットは TCP や UDP などの通信の終端である.
ソケットは, コンピュータの特定のポート番号と関連づけられる. ポート番号で識別できるため, 一台のホストで複数のソケットを同時に取り扱うことが可能.
ソケットを表現するクラスは次の4つが用意されている. これらのクラスはすべて java.net パッケージに含まれている.
InetAddress は IP アドレスを取り扱うためのクラスである.
InetAddress のサブラクスは:
1. Inet4Address
2. Inet6Address
InetAddress のインスタンスを新しく生成するには, 通常は [コンストラクタは用いない]. 次のようなクラスメソッドを使うこと:
1. static InetAddress getByAddress(byte[] address);
2. static InetAddress getByAddress(String name, byte[] address);
3. static InetAddress getByName(String name);
InetAddress は, ホスト名または IP アドレス (もしくはその両方) を指定して作成することができる. 例としては下記のようになる:
1. InetAddress adr = InetAddress.getByAddress(new byte[] {(byte)211, 125, 78, 77});
2. InetAddress adr = InetAddress.getByName("211,125,78,77");
SocketAddress はソケットを識別するアドレスを表すクラス.
TCP や UDP などの TCP/IP プロトコルスイートにおけるソケットアドレスを表すには InetSocketAddress を用いる.
注意:
InetSocketAddress は SocketAddress のサブクラス
InetSocketAddress には次の3つのコンストラクタが用意されている:
1. public InetSocketAddress(String hostname, int port);
2. public InetSocketAddress(InetAddress addr, int port);
3. public InetSocketAddress(int port);
Socket クラスはソケットを表すクラス.
Socket はローカルホストの特定のポートに関連づけられる. また, その Socket を実際に通信利用するには, 接続先のアドレスも指定されていなければいけない.
Socket クラスのいくつかのコンストラクタは下記のようになる:
1. Socket(InetAddress address, int port);
2. Socket(InetAddress address, int port, InetAddress localAddr, int localPort);
3. Socket(String host, int port, InetAddress localAddr, int localPort);
注意:
ローカルのアドレス/ポートを指定していないものは, 自動的に割り振られたポートポートに関連づけられる.
Socket を利用した通信は, 入出力用のストリームを介して実現される. 入出力用のストリームを取得するには下記のメソッドを用いる.
ここのサンプルには, 2つのプログラムによって構成されている:
1. クライアントから送信された文字列を [そのまま送り返す] サーバプログラム
2. サーバに接続するクライアントプログラム
EchoServer.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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 = 51015;
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){
//
}
}
}
}
|
次に, クライアントアプリケーションを示す. キーボードからの入力をサーバプログラムに送信し, 送り返されてきた文字列をコンソールに出力するプログラム. 空行の入力があった時, 接続を切断して終了するようにする.
EchoClient.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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 = 51015;
public static void main(String[] args){
Socket socket = null;
try{
// 新しいソケットを作成
socket = new Socket(args[0], ECHO_PORT);
// 接続されたソケットの接続先情報を表示している
System.out.println("接続した: " + socket.getRemoteSocketAddress());
/*
ソケットに対して入出力を行うための 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));
/*
サーバとの通信処理を行っている. キーボードから入力された文字列をサーバに対して送信し, 送り返されてきた文字列を表示する.
ループによって空行が入力されるまで処理を繰り返している.
*/
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());
}
}
}
}
|
EchoClient.java の実行結果:
[wtopia]$ java EchoClient 127.0.0.1 [~/src_py/sphinx/java.net/EchoCS]
接続した: /127.0.0.1:51015
Hello-1
Hello-1
Hello-2
Hello-2
Hello-3
Hello-3
Hello-4
Hello-4
(空行)
EchoServer.java の実行結果:
[wtopia]$ java EchoServer [~/src_py/sphinx/java.net/EchoCS]
EchoServer が起動した, port は: 51015
接続された: /127.0.0.1:55415
受信: Hello-1
送信:Hello-1
受信: Hello-2
送信:Hello-2
受信: Hello-3
送信:Hello-3
受信: Hello-4
送信:Hello-4
注意:
[空行] を入力すると, ソケットが切断されている.
インターネット上のプロトコルとして, Daytime プロトコルというものがある. Daytime プロトコルにおけるサーバは, ソケットに接続すると, 接続してきたクライアントに対して現在の時刻を送り返し, コネクションを切断する.
DaytimeClient.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class DaytimeClient{
public static final int DAYTIME_PORT = 13;
public static void main(String[] args){
Socket socket = null;
if(args.length == 0){
System.out.println("引数に接続先のサーバを指定してください: ");
return;
}
try{
// 引数で指定したホストに接続する
socket = new Socket(args[0], DAYTIME_PORT);
System.out.println("接続した : " + socket.getRemoteSocketAddress());
// データ受信用のリーダ作成
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while( (line = in.readLine()) != null ){
System.out.println(line);
}
in.close();
}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(socket != null){
socket.close();
}
}catch(IOException e){
//
}
System.out.println("切断された : " + socket.getRemoteSocketAddress());
}
}
}
|
上記のプログラムの実行結果:
[wtopia Daytime]$ java DaytimeClient time.nist.gov
接続した : time.nist.gov/192.43.244.18:13
55798 11-08-25 13:23:59 50 0 0 743.9 UTC(NIST) *
切断された : time.nist.gov/192.43.244.18:13