筑波大学 システム情報工学研究科
コンピュータサイエンス専攻, 電子・情報工学系
新城 靖
<yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~syspro/2007/No7_files/echo-server-java.html
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~syspro/2007/
http://www.coins.tsukuba.ac.jp/~yas/
1: /*
2: EchoServerSingle.java -- 文字列を送受信するサーバ(TCP/IP, Java版, スレッドなし)
3: ~yas/syspro/ipc/EchoServer.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: System.err.println("Usage: % java EchoServer port");
16: System.exit( -1 );
17: }
18: int portno = Integer.parseInt( argv[0] );
19: echo_server( portno );
20: }
引数として、ポート番号を取る。
22: public static void echo_server( 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: }
ServerSocket() は、引数で与えられたポート番号を使って接続要求受付用ポー トを作成し、それに対応した 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.println("run telnet "+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.println("connection (hash=="+com.hashCode()+") from "+peerhostaddr+":"+peerportno );
47: }
print_my_host_port() と tcp_peeraddr_print() は、それぞれ同じ同名のC の関数と同じ働きをする。
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.println("received (hash=="+com.hashCode()+") "+
27: line.length()+" characters, ["+line+"]");
28: out.println( line );
29: }
30: stdout.println("connection (hash=="+com.hashCode()+") closed.");
31: in.close();
32: out.close();
33: com.close();
34: }
35: catch( IOException e )
36: {
37: stderr.println( e );
38: }
39: }
40: static java.io.BufferedReader stdin =
41: new java.io.BufferedReader( new java.io.InputStreamReader(System.in) );
42: static java.io.PrintStream stdout = System.out;
43: static java.io.PrintStream stderr = System.err;
44: }
echoサービスのクライアント
と同様に、Socket から BufferedReader と PrintStream を生成している。
そして、readLine() や println() により通信を行っている。
% diff -c EchoServerSingle.java EchoServer.java
*** EchoServerSingle.java Sun May 9 20:01:50 2004
--- EchoServer.java Sun May 9 19:59:33 2004
***************
*** 1,13 ****
/*
! EchoServerSingle.java -- 文字列を送受信するサーバ(TCP/IP, Java版, スレッドなし)
~yas/syspro/ipc/EchoServer.java
! Created on 2004/05/09 20:00:24
*/
import java.net.*;
import java.io.*;
! class EchoServerSingle
{
public static void main(String argv[]) throws IOException {
if( argv.length != 1 )
--- 1,13 ----
/*
! EchoServer.java -- 文字列を送受信するサーバ(TCP/IP, Java版)
~yas/syspro/ipc/EchoServer.java
! Created on 2004/02/14 16:22:13
*/
import java.net.*;
import java.io.*;
! class EchoServer
{
public static void main(String argv[]) throws IOException {
if( argv.length != 1 )
***************
*** 27,34 ****
{
Socket com = acc.accept();
tcp_peeraddr_print( com );
! EchoServerWorker esw = new EchoServerWorker(com);
! esw.run();
}
}
public static void print_my_host_port( int portno ) throws UnknownHostException
--- 27,34 ----
{
Socket com = acc.accept();
tcp_peeraddr_print( com );
! Thread th = new Thread( new EchoServerWorker(com) );
! th.start();
}
}
public static void print_my_host_port( int portno ) throws UnknownHostException
%