筑波大学 システム情報工学研究科 コンピュータサイエンス専攻, 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~syspro/2010/No7_files/echo-server-java.html
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~syspro/2010/
http://www.coins.tsukuba.ac.jp/~yas/
1: /* 2: EchoServerSingle.java -- 文字列を送受信するサーバ(TCP/IP, Java版, スレッドなし) 3: ~yas/syspro/ipc/EchoServerSingle.java 4: Created on 2004/05/09 20:00:24 5: */ 6: 7: import java.net.*; 8: import java.io.*; 9: 10: class EchoServerSingle 11: { 12: public static void main(String argv[]) throws IOException { 13: if( argv.length != 1 ) 14: { 15: stderr.printf("Usage: %% java EchoServerSingle port\n"); 16: System.exit( -1 ); 17: } 18: int portno = Integer.parseInt( argv[0] ); 19: echo_server_single( portno ); 20: } 21:引数として、ポート番号を取る。
22: public static void echo_server_single( int portno ) throws IOException 23: { 24: ServerSocket acc = new ServerSocket( portno ); 25: print_my_host_port( portno ); 26: while( true ) 27: { 28: Socket com = acc.accept(); 29: tcp_peeraddr_print( com ); 30: EchoServerWorker esw = new EchoServerWorker(com); 31: esw.run(); 32: } 33: }
echo_server_single() は、 引数で与えられたポート番号を使って接続要求受付用ポー トを作成し、それに対応した ServerSocket のオブジェクトを返す。このオブ ジェクトは、Socket のオブジェクトとは異なり、そまままでは通信に用いる ことはできない。
print_my_host_port() は、telnet で接続する時のヒントを表示する。
サーバのプログラムの特徴は、内部に無限ループを持っていることである。 サーバは、普通の状態では、終了しない。
accept() は、接続要求を待つメソッドである。クライアントから接続が来る まで、システムコールを実行したまま止まっているように見える。接続要求が 届くと、TCP/IP通信路の開設され、通信用ポートに対応したSocket クラスの オブジェクトが返される。このオブジェクトは、クライアント側と同様に getInputStream() や getOutputStream() により入出力可能なストリームを作 り出すことができる。
tcp_peeraddr_print() は、通信相手の IP アドレスとポート番号を表示する関数である。
以後の仕事は、EchoServerWorker というクラスのオブジェクトを作成して行 わせている。コンストラクタでは、Socket クラスのオブジェクトを渡してい だけであり、実際の処理は何も行われない。実際の処理は、run() メソッドで 行われる。
34: public static void print_my_host_port( int portno ) throws UnknownHostException 35: { 36: InetAddress ia = java.net.InetAddress.getLocalHost(); 37: String hostname = ia.getHostName(); 38: stdout.printf("run telnet %s %d\n",hostname, portno ); 39: }
40: public static void tcp_peeraddr_print( Socket com ) 41: { 42: InetSocketAddress isa = (InetSocketAddress)com.getRemoteSocketAddress(); 43: InetAddress ia = isa.getAddress(); 44: String peerhostaddr = ia.getHostAddress(); 45: int peerportno = isa.getPort(); 46: stdout.printf("connection (hash== %s) from %s:%d\n", com.hashCode(), 47: peerhostaddr, peerportno ); 48: }
49: static java.io.BufferedReader stdin = 50: new java.io.BufferedReader( new java.io.InputStreamReader(System.in) ); 51: static java.io.PrintStream stdout = System.out; 52: static java.io.PrintStream stderr = System.err; 53: }
1: /* 2: EchoServerWorker.java -- 文字列を送受信するサーバ/ワーカ(TCP/IP, Java版) 3: ~yas/syspro/ipc/EchoServerWorker.java 4: */ 5: 6: import java.net.*; 7: import java.io.*; 8: 9: public class EchoServerWorker implements Runnable 10: { 11: Socket com ; 12: EchoServerWorker( Socket com ) 13: { 14: this.com = com ; 15: } 16: public void run() 17: { 18: try 19: { 20: BufferedReader in = new BufferedReader( 21: new InputStreamReader( com.getInputStream() )); 22: PrintStream out = new PrintStream( com.getOutputStream() ); 23: String line; 24: while( (line = in.readLine())!= null ) 25: { 26: stdout.printf("received (hash==%s) %d characters, [%s]\n", 27: com.hashCode(), line.length(),line ); 28: out.printf("%s\n", line ); 29: } 30: stdout.printf("connection (hash==%s) closed.\n", com.hashCode()); 31: in.close(); 32: out.close(); 33: com.close(); 34: } 35: catch( IOException e ) 36: { 37: stderr.println( e ); 38: } 39: } 40: 41: static java.io.BufferedReader stdin = 42: new java.io.BufferedReader( new java.io.InputStreamReader(System.in) ); 43: static java.io.PrintStream stdout = System.out; 44: static java.io.PrintStream stderr = System.err; 45: }echoサービスのクライアント と同様に、Socket から BufferedReader と PrintStream を生成している。 そして、readLine() や println() により通信を行っている。