システムプログラム(第8回): スレッドによる複数のクライアントに対するサービスの同時提供(Java版)

                                       筑波大学 システム情報系 情報工学域
                                       新城 靖
                                       <yas@cs.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~syspro/2018/2018-06-06 /echo-server-java-thread.html
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~syspro/2018/
http://www.coins.tsukuba.ac.jp/~yas/

EchoServer.java

EchoServer.java は、 EchoServerSingle.java をスレッドを用いて修正して、複数のクライアントに対してサービスを同時に 提供できるようにしたものである。違いは、new Thread(...) の行と、その次 の行だけである。
  23:	        public static void echo_server( int portno ) throws IOException
  24:	        {
  25:	                ServerSocket acc = new ServerSocket( portno );
  26:	                print_my_host_port( portno );
  27:	                while( true )
  28:	                {
  29:	                        stdout.printf("accepting incoming connections (hash== %s) ...\n", 
  30:	                                      acc.hashCode());
  31:	                        Socket com = acc.accept();
  32:	                        tcp_peeraddr_print( com );
  33:	                        Thread th = new Thread( new EchoServerWorker(com) );
  34:	                        th.start();
  35:	                }
  36:	        }
全体の差分は、以下のようになっている。
 $ diff -c  EchoServerSingle.java EchoServer.java
 *** EchoServerSingle.java	2018-07-22 20:48:30.000000000 +0900 --- EchoServer.java	2018-07-27 14:57:38.000000000 +0900 ***************
 *** 1,26 ****
   /*
 !   EchoServerSingle.java -- 文字列を送受信するサーバ(TCP/IP, Java版, スレッドなし)
 !   ~yas/syspro/ipc/EchoServerSingle.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 )
		 {
 ! 			stderr.printf("Usage: %% java EchoServerSingle port\n");
			 System.exit( -1 );
		 }
		 int portno = Integer.parseInt( argv[0] );
 ! 		echo_server_single( portno );
	 }

 ! 	public static void echo_server_single( int portno ) throws IOException
	 {
		 ServerSocket acc = new ServerSocket( portno );
		 print_my_host_port( portno );
 --- 1,26 ----
   /*
 !   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 )
		 {
 ! 			stderr.printf("Usage: %% java EchoServer port\n");
			 System.exit( -1 );
		 }
		 int portno = Integer.parseInt( argv[0] );
 ! 		echo_server( portno );
	 }

 ! 	public static void echo_server( int portno ) throws IOException
	 {
		 ServerSocket acc = new ServerSocket( portno );
		 print_my_host_port( portno );
 ***************
 *** 30,37 ****
				       acc.hashCode();
			 Socket com = acc.accept();
			 tcp_peeraddr_print( com );
 ! 			EchoServerWorker esw = new EchoServerWorker(com);
 ! 			esw.run();
		 }
	 }
	 public static void print_my_host_port( int portno )
 --- 30,37 ----
				       acc.hashCode();
			 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 )

))

実行例

実行例。 サーバ側。サーバは、終了しないので、最後に、^C を押して、割り込みを掛け て終了させる。 注意:全員がポート番号 1231 を使うとプログラムが動かないことがある。
$ cp ~yas/syspro/ipc/EchoServer{,Worker}.java . [←]
$ ls *java [←]
EchoServer.java         EchoServerWorker.java
$ javac EchoServer.java EchoServerWorker.java [←]
$ ls *class [←]
EchoServer.class        EchoServerWorker.class
$ java  EchoServer 1231 [←]
run telnet crocus39.coins.tsukuba.ac.jp 1231
accepting incoming connections (hash== 785360174) ...
connection (hash== 1113949956) from 130.158.86.247:50100
accepting incoming connections (hash== 785360174) ...
received (com hash==1113949956) 5 characters, [012
]
connection (hash== 967831570) from 130.158.86.248:49708
accepting incoming connections (hash== 785360174) ...
received (com hash==967831570) 5 characters, [abc
]
received (com hash==967831570) 5 characters, [def
]
received (com hash==1113949956) 5 characters, [345
]
connection (com hash==1113949956) closed.
connection (com hash==967831570) closed.
^C
$ []
クライアント側(その1)。
$ telnet crocus39.coins.tsukuba.ac.jp 1231 [←]
Trying 130.158.86.249...
Connected to crocus39.coins.tsukuba.ac.jp.
Escape character is '^]'.
012[←]
012
345[←]
345
^]
telnet> ^D
Connection closed.
$ []
クライアント側(その2)。
$ telnet crocus39.coins.tsukuba.ac.jp 1231 [←]
Trying 130.158.86.249...
Connected to crocus39.coins.tsukuba.ac.jp.
Escape character is '^]'.
abc[←]
abc
def[←]
def
^]
telnet> ^D
Connection closed.
$ []

$ telnet cosmos10 1231 [←]
Trying 130.158.86.150...
Connected to cosmos10.coins.tsukuba.ac.jp.
Escape character is '^]'.
abc[←]
abc
def[←]
def
^]
telnet> quit[←]
Connection closed.
$ []

スレッドの切り離し

Java のスレッドが残っていると、main() を実行しているスレッドが終了して も、プログラム全体は終了しない。main() を実行しているスレッドが終了する と終了するようにするためには、次のように setDaemon() で切り離す方法があ る。
    Thread th = new Thread( new EchoServerWorker(com) );
    th.setDaemon(true);
    th.start();

Last updated: 2018/06/03 19:17:10
Yasushi Shinjo / <yas@cs.tsukuba.ac.jp>