並列分散ソフトウェア
電子・情報工学系
新城 靖
<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-forkrun 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 1231Trying 130.158.86.1... Connected to adonis1. Escape character is '^]'. 012
012 345
345 ^] telnet> quit
Connection closed. %
----------------------------------------------------------------------
---------------------------------------------------------------------- % % telnet adonis1 1231Trying 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-pthreadrun 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 1231Trying 130.158.86.1... Connected to adonis1. Escape character is '^]'. 012
012 345
345 ^] telnet> quit
Connection closed. %
----------------------------------------------------------------------
---------------------------------------------------------------------- % % telnet adonis1 1231Trying 130.158.86.1... Connected to adonis1. Escape character is '^]'. abc
abc def
def ^] telnet> quit
Connection closed. %
----------------------------------------------------------------------