筑波大学 システム情報工学研究科
コンピュータサイエンス専攻, 電子・情報工学系
新城 靖
<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() により通信を行っている。