筑波大学 システム情報工学研究科 コンピュータサイエンス専攻, 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.coins.tsukuba.ac.jp/~syspro/2009/No8_files/echo-server-pthread.html
あるいは、次のページから手繰っていくこともできます。
http://www.coins.tsukuba.ac.jp/~syspro/2009/
http://www.coins.tsukuba.ac.jp/~yas/
echo-server-pthread.c
では、プロセスではなく
スレッドを作っている。
1: 2: /* 3: echo-server-pthread.c -- 受け取った文字列をそのまま返すサーバ(pthread版) 4: ~yas/syspro/ipc/echo-server-pthread.c 5: Created on 2002/02/04 21:17:04 6: */ 7: #include <stdio.h> 8: #include <stdlib.h> /* exit() */ 9: #include <sys/types.h> /* socket(), time() */ 10: #include <sys/socket.h> /* socket() */ 11: #include <netinet/in.h> /* struct sockaddr_in */ 12: #include <pthread.h> /* pthread_create */ 13: #include <netdb.h> /* getnameinfo() */ 14: #include <string.h> /* strlen() */ 15: 16: extern void echo_server( int portno ); 17: extern void echo_reply( int com ); 18: extern void print_my_host_port( int portno ); 19: extern void tcp_peeraddr_print( int com ); 20: extern void sockaddr_print( struct sockaddr *addrp, socklen_t addr_len ); 21: extern tcp_acc_port( int portno ); 22: extern int fdopen_sock( int sock, FILE **inp, FILE **outp ); 23: 24: main( int argc, char *argv[] ) 25: { 26: int portno ; 27: if( argc != 2 ) 28: { 29: fprintf( stdout,"Usage: %s portno\n",argv[0] ); 30: exit( -1 ); 31: } 32: portno = strtol( argv[1],0,10 ); 33: echo_server( portno ); 34: } 35:main() は、 forkなし版 や fork版 とほとんど同じである。
36: void 37: echo_server( int portno ) 38: { 39: int acc,com ; 40: pthread_t worker ; 41: acc = tcp_acc_port( portno ); 42: if( acc<0 ) 43: exit( -1 ); 44: print_my_host_port( portno ); 45: while( 1 ) 46: { 47: if( (com = accept( acc,0,0 )) < 0 ) 48: { 49: perror("accept"); 50: exit( -1 ); 51: } 52: tcp_peeraddr_print( com ); 53: if( pthread_create( &worker, NULL, (void *)echo_reply, (void *)com) 54: != 0 ) 55: { 56: perror("pthread_create()"); 57: exit( 1 ); 58: } 59: pthread_detach( worker ); 60: } 61: } 62:
このプログラムの特徴を以下にまとめる。
他の関数は、fork版、forkなし版とと同じである。
% diff -c echo-server-nofork-fdopen.c echo-server-pthread.c *** echo-server-nofork-fdopen.c Mon Jun 8 18:46:58 2009 --- echo-server-pthread.c Mon Jun 8 18:53:50 2009 *************** *** 1,16 **** /* ! echo-server-nofork-fdopen.c -- 受け取った文字列をそのまま返すサーバ(fork無し版) ! ~yas/syspro/ipc/echo-server-nofork-fdopen.c ! Created on 2004/05/09 19:08:47 */ #include <stdio.h> #include <stdlib.h> /* exit() */ ! #include <sys/types.h> /* socket(), wait4() */ #include <sys/socket.h> /* socket() */ #include <netinet/in.h> /* struct sockaddr_in */ ! #include <sys/resource.h> /* wait4() */ ! #include <sys/wait.h> /* wait4() */ #include <netdb.h> /* getnameinfo() */ #include <string.h> /* strlen() */ --- 1,15 ---- /* ! echo-server-pthread.c -- 受け取った文字列をそのまま返すサーバ(pthread版) ! ~yas/syspro/ipc/echo-server-pthread.c ! Created on 2002/02/04 21:17:04 */ #include <stdio.h> #include <stdlib.h> /* exit() */ ! #include <sys/types.h> /* socket(), time() */ #include <sys/socket.h> /* socket() */ #include <netinet/in.h> /* struct sockaddr_in */ ! #include <pthread.h> /* pthread_create */ #include <netdb.h> /* getnameinfo() */ #include <string.h> /* strlen() */ *************** *** 38,43 **** --- 37,43 ---- echo_server( int portno ) { int acc,com ; + pthread_t worker ; acc = tcp_acc_port( portno ); if( acc<0 ) exit( -1 ); *************** *** 50,56 **** exit( -1 ); } tcp_peeraddr_print( com ); ! echo_reply( com ); } } --- 50,62 ---- exit( -1 ); } tcp_peeraddr_print( com ); ! if( pthread_create( &worker, NULL, (void *)echo_reply, (void *)com) ! != 0 ) ! { ! perror("pthread_create()"); ! exit( 1 ); ! } ! pthread_detach( worker ); } } %実行例。
サーバ側。サーバは、終了しないので、最後に、^C を押して、割り 込みを掛けて終了させる。
注意:全員がポート番号 1231 を使うとプログラムが動かないことがある。
% ./echo-server-pthread
Usage: ./echo-server-pthread portno
% ./echo-server-pthread 1231
run telnet azalea20 1231
[1376] connection (fd==4) from 130.158.86.40:49838
[1376] received (fd==4) 5 bytes, [012
]
[1376] connection (fd==6) from 130.158.86.207:51885
[1376] received (fd==6) 5 bytes, [abc
]
[1376] received (fd==6) 5 bytes, [def
]
[1376] connection (fd==6) closed.
[1376] received (fd==4) 5 bytes, [345
]
[1376] connection (fd==4) closed.
^C
%
クライアント側(その1)。
% telnet azalea20 1231
Trying 130.158.86.40...
Connected to azalea20.coins.tsukuba.ac.jp.
Escape character is '^]'.
012
012
345
345
^]
telnet> ^D
Connection closed.
%
クライアント側(その2)。
% telnet azalea20 1231
Trying 130.158.86.40...
Connected to azalea20.coins.tsukuba.ac.jp.
Escape character is '^]'.
abc
abc
def
def
^]
telnet> ^D
Connection closed.
%