並列分散ソフトウェア 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2000/2001-01-18
fork-pthread.html
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/sie/
http://www.is.tsukuba.ac.jp/~yas/index-j.html
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html
◆echo-server-fork(forkを使ったプログラム)
TCP/IP のポート番号 7 (echo) では、受け取ったデータをそのまま返すサー ビスを提供している。以下は、これと同じような機能を提供するサーバである。 複数の接続先(クライアント)の要求を同時に処理するために、クライアント ごとに fork() システム・コールで専用の子プロセスを作っている。
---------------------------------------------------------------------- 1: 2: /* 3: echo-server-fork.c -- 受け取った文字列をそのまま返すサーバ(fork版) 4: http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2000/examples/echo-server-fork.c 5: $Header: /home/hlla/yas/cvs/sie-pdsoft-2000-examples/echo-server-fork.c,v 1.1 2001/01/06 22:05:53 yas Exp $ 6: Start: 1997/06/09 19:46:40 7: */ 8: #include <stdio.h> 9: #include <sys/types.h> /* socket(), time() */ 10: #include <sys/socket.h> /* socket() */ 11: #include <netinet/in.h> /* struct sockaddr_in */ 12: ... 20: main( int argc, char *argv[] ) 21: { 22: int portno ; 23: if( argc >= 3 ) 24: { 25: fprintf( stdout,"Usage: %s host port\n",argv[0] ); 26: exit( -1 ); 27: } 28: if( argc == 2 ) 29: portno = atoi( argv[1] ); 30: else 31: portno = getuid(); 32: echo_server( portno ); 33: } 34: 35: void echo_server( int portno ) 36: { 37: int acc,com ; 38: pid_t child_pid ; 39: acc = tcp_acc_port( portno ); 40: if( acc<0 ) 41: exit( -1 ); 42: print_host_port( portno ); 43: while( 1 ) 44: { 45: if( (com = accept( acc,0,0 )) < 0 ) 46: { 47: perror("accept"); 48: exit( -1 ); 49: } 50: tcp_peeraddr_print( com ); 51: if( (child_pid=fork()) > 0 ) /* parent */ 52: { 53: close( com ); 54: } 55: else if( child_pid == 0 ) 56: { 57: close( acc ); 58: echo_reply( com ); 59: printf("[%d,%d] connection closed.\n",getpid(),com ); 60: close( com ); 61: exit( 0 ); 62: } 63: } 64: } 65: 66: void echo_reply( int com ) 67: { 68: char buf[BUFSIZ] ; 69: int rcount ; 70: int wcount ; 71: 72: while( (rcount=read(com,buf,BUFSIZ)) > 0 ) 73: { 74: if( (wcount=writen(com,buf,rcount))!= rcount ) 75: { 76: perror("write"); 77: exit( 1 ); 78: } 79: printf("[%d,%d] ",getpid(),com ); 80: fflush( stdout ); 81: write( 1, buf, rcount ); 82: } 83: } ... ----------------------------------------------------------------------実行例。
サーバ側。サーバは、終了しないので、最後に、^C か Del を押して、割り込みを掛けて終了させる。
クライアント側(その1)。---------------------------------------------------------------------- % ./echo-server-fork run telnet adonis1 1231 [4535,4] connection from 130.158.86.1:2368 [4539,4] 012 [4535,4] connection from 130.158.86.9:15629 [4542,4] abc [4542,4] def [4542,4] connection closed. [4539,4] 345 [4539,4] connection closed. ^C % ----------------------------------------------------------------------
クライアント側(その2)。---------------------------------------------------------------------- % telnet adonis1 1231 Trying 130.158.86.1... Connected to adonis1. Escape character is '^]'. 012 012 345 345 ^] telnet> quit Connection closed. % ----------------------------------------------------------------------
---------------------------------------------------------------------- % % telnet adonis1 1231 Trying 130.158.86.1... Connected to adonis1. Escape character is '^]'. abc abc def def ^] telnet> quit Connection closed. % ----------------------------------------------------------------------
◆echo-server-pthread(pthreadを使ったプログラム)
fork() の代わりに、Pthread を使う。---------------------------------------------------------------------- 1: 2: /* 3: echo-server-fork.c -- 受け取った文字列をそのまま返すサーバ(pthread版) 4: http://www.hlla.is.tsukuba.ac.jp/~yas/sie/pdsoft-2000/examples/echo-server-pthread.c 5: $Header: /home/hlla/yas/cvs/sie-pdsoft-2000-examples/echo-server-pthread.c,v 1.1 2001/01/06 22:05:53 yas Exp $ 6: <-- ~yas/syspro1-1998/ipc/RCS/echo-server-fork.c,v 1.5 1997/06/09 21:28:27 yas Exp $ 7: Start: 1997/06/09 19:46:40 8: */ 9: #include <stdio.h> 10: #include <sys/types.h> /* socket(), time() */ 11: #include <sys/socket.h> /* socket() */ 12: #include <netinet/in.h> /* struct sockaddr_in */ 13: #include <pthread.h> ... 22: main( int argc, char *argv[] ) 23: { 24: int portno ; 25: if( argc >= 3 ) 26: { 27: fprintf( stdout,"Usage: %s host port\n",argv[0] ); 28: exit( -1 ); 29: } 30: if( argc == 2 ) 31: portno = atoi( argv[1] ); 32: else 33: portno = getuid(); 34: echo_server( portno ); 35: } 36: 37: void 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_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: 63: void echo_reply( int com ) 64: { 65: char buf[BUFSIZ] ; 66: int rcount ; 67: int wcount ; 68: 69: while( (rcount=read(com,buf,BUFSIZ)) > 0 ) 70: { 71: if( (wcount=writen(com,buf,rcount))!= rcount ) 72: { 73: perror("write"); 74: exit( 1 ); 75: } 76: printf("[%d,%d,%d] ",getpid(),pthread_self(),com ); 77: fflush( stdout ); 78: write( 1, buf, rcount ); 79: } 80: printf("[%d,%d,%d] connection closed.\n",getpid(),pthread_self(),com ); 81: close( com ); 82: } <以下省略> ----------------------------------------------------------------------実行例。
サーバ側。サーバは、終了しないので、最後に、^C か Del を押して、割り込みを掛けて終了させる。
クライアント側(その1)。---------------------------------------------------------------------- % ./echo-server-pthread run telnet adonis1 1231 [4509,65536,4] connection from 130.158.86.1:2367 [4509,65537,4] 012 [4509,65536,5] connection from 130.158.86.9:15628 [4509,65538,5] abc [4509,65538,5] def [4509,65538,5] connection closed. [4509,65537,4] 345 [4509,65537,4] connection closed. ^C % ----------------------------------------------------------------------
クライアント側(その2)。---------------------------------------------------------------------- % telnet adonis1 1231 Trying 130.158.86.1... Connected to adonis1. Escape character is '^]'. 012 012 345 345 ^] telnet> quit Connection closed. % ----------------------------------------------------------------------
---------------------------------------------------------------------- % % telnet adonis1 1231 Trying 130.158.86.1... Connected to adonis1. Escape character is '^]'. abc abc def def ^] telnet> quit Connection closed. % ----------------------------------------------------------------------