システム・プログラムI
電子・情報工学系
新城 靖
<yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro1-1997/1997-06-17
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.hlla.is.tsukuba.ac.jp/~yas/index-j.html
ヒント:accept() で止まる前に、wait() する方法がある。ただし、単純に wait() すると、fork() の効果がまったくなくなる。子プロセスが終了したと きだけ、wait() したい。それには、waitpid() や wait3(), wait4() で、あ るオプションを使うとよい。
ヒント:子プロセスの終了を、ソフトウェア割り込み(SIGCLD)で知る方法もあ る。複数の子プロセスが終了しても、割り込みは1回しか起こらないことがあ ることに注意しなさい。
HTTP のレベルで、クライアントとサーバの間を中継するプログラムを、HTTP Proxy と呼ぶ。HTTP Proxy は、クライアントから見ると、サーバに見え、サー バから見ると、クライアントに見える。
HTTP Proxy は、次のような目的に使われる。
HTTP proxy 作りなさい。キャッシングが、防火壁越えか、フィルタリングの 機能を付けなさい。
----------------------------------------------------------------------
1:
2: /*
3: echo-client-udp.c -- 文字列を送受信するクライアント(UDP/IP版)
4: /usr/local/LECTURES/syspro-1997-shinjo/ipc/echo-client-udp.c
5: $Header: echo-client-udp.c,v 1.2 97/06/16 22:11:03 yas Exp $
6: Start: 1997/06/16 21:22:26
7: */
8: #include <stdio.h>
9: #include <sys/socket.h> /* socket() */
10: #include <netinet/in.h> /* struct sockaddr_in */
11: #include <netdb.h> /* gethostbyname() */
12:
13: main( argc,argv )
14: int argc ;
15: char *argv[] ;
16: {
17: if( argc != 3 )
18: {
19: fprintf( stdout,"Usage: %s host port\n",argv[0] );
20: exit( -1 );
21: }
22: recho( argv[1],atoi(argv[2]) );
23: }
24:
25: #define BUFFSIZE 1024
26:
27: recho( hostname,portno )
28: char *hostname ;
29: int portno ;
30: {
31: int s, rcount, scount, len, fromlen ;
32: struct sockaddr_in to, from ;
33: char buff[BUFFSIZE];
34:
35: s = udp_port( 0 );
36: if( s<0 )
37: exit( -1 );
38: printf("my port is "); sockname_print( s );
39:
40: sprintf( buff,"hello" );
41: len = strlen( buff ) + 1 ;
42: sockaddr_in_init( &to, hostname, portno );
43: if( scount = sendto( s, buff, len, 0, &to, sizeof(to) )!= len )
44: {
45: perror("sendto()");
46: exit( 1 );
47: }
48:
49: fromlen = sizeof( from );
50: if( (rcount = recvfrom( s, buff, BUFFSIZE, 0, &from, &fromlen )) < 0 )
51: {
52: perror("recvfrom()");
53: exit( 1 );
54: }
55: printf("received from "); sockaddr_in_print( &from );
56: buff[rcount] = 0 ;
57: printf("%d bytes received. [%s] \n", rcount, buff );
58:
59: close( s );
60: }
61:
62: int udp_port( portno )
63: int portno ;
64: {
65: struct hostent *hostent ;
66: struct sockaddr_in addr ;
67: int addr_len ;
68: int s ;
69:
70: if( (s = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
71: {
72: perror("socket");
73: return( -1 );
74: }
75:
76: addr.sin_family = AF_INET ;
77: addr.sin_addr.s_addr = INADDR_ANY ;
78: addr.sin_port = htons( portno );
79:
80: if( bind(s,&addr,sizeof(addr)) < 0 )
81: {
82: perror( "bind: " );
83: fprintf(stderr,"port number %d is already used. kill another program.", portno );
84: return( -1 );
85: }
86: return( s );
87: }
88:
89: sockaddr_in_init( addr, hostname, portno )
90: struct sockaddr_in *addr ;
91: {
92: struct hostent *hostent ;
93: addr->sin_family = AF_INET ;
94: if( (hostent = gethostbyname( hostname )) == NULL )
95: {
96: fprintf(stderr,"unknown host %s\n",hostname );
97: return( -1 );
98: }
99: bcopy( hostent->h_addr, &addr->sin_addr, hostent->h_length );
100: addr->sin_port = htons( portno );
101: return( 0 );
102: }
103:
104: sockaddr_in_print( addr )
105: struct sockaddr_in *addr ;
106: {
107: union {
108: int i ;
109: unsigned char byte[4] ;
110: } x ;
111: x.i = addr->sin_addr.s_addr ;
112: printf("sockaddr_in: %d.%d.%d.%d:%d\n",
113: x.byte[0],x.byte[1],x.byte[2],x.byte[3],
114: ntohs( addr->sin_port ));
115: }
116:
117: sockname_print( s )
118: {
119: struct sockaddr_in addr ;
120: int len ;
121: len = sizeof( addr );
122: if( getsockname( s, &addr, &len )< 0 )
123: {
124: perror("getsockname");
125: exit( -1 );
126: }
127: sockaddr_in_print( &addr );
128: }
----------------------------------------------------------------------
bind() では、INADDR_ANY, porno=0 で名前を付けている。これにより、オペ レーティング・システムが、空いているポートを割り当てる。こうして割り当 てられた番号は、後で getsockname() で調べることができる。
実行例。
---------------------------------------------------------------------- % ./echo-client-udp localhost 7my port is sockaddr_in: 0.0.0.0:2751 received from sockaddr_in: 127.0.0.1:7 6 bytes received. [hello] % ./echo-client-udp adonis5 7
my port is sockaddr_in: 0.0.0.0:2786 received from sockaddr_in: 130.158.87.5:7 6 bytes received. [hello] %
----------------------------------------------------------------------
----------------------------------------------------------------------
1:
2: /*
3: echo-server-udp.c -- 文字列を送受信するサーバ(UDP/IP版)
4: /usr/local/LECTURES/syspro-1997-shinjo/ipc/echo-server-udp.c
5: $Header: echo-server-udp.c,v 1.2 97/06/16 22:10:53 yas Exp $
6: Start: 1997/06/16 21:22:26
7: */
8: #include <stdio.h>
9: #include <sys/socket.h> /* socket() */
10: #include <netinet/in.h> /* struct sockaddr_in */
11: #include <netdb.h> /* gethostbyname() */
12:
13: main( argc,argv )
14: int argc ;
15: char *argv[] ;
16: {
17: int portno ;
18: if( argc >= 3 )
19: {
20: fprintf( stdout,"Usage: %s host port\n",argv[0] );
21: exit( -1 );
22: }
23: if( argc == 2 )
24: portno = atoi( argv[1] );
25: else
26: portno = getuid();
27: echo_server_udp( portno );
28: }
29:
30: #define BUFFSIZE 1024
31:
32: echo_server_udp( portno )
33: int portno ;
34: {
35: int s, rcount, scount, addrlen ;
36: struct sockaddr_in addr ;
37: char buff[BUFFSIZE];
38:
39: s = udp_port( portno );
40: if( s<0 )
41: exit( -1 );
42: printf("my port is "); sockname_print( s );
43:
44: while( 1 )
45: {
46: addrlen = sizeof( addr );
47: if( (rcount = recvfrom( s, buff, BUFFSIZE, 0, &addr, &addrlen )) < 0 )
48: {
49: perror("recvfrom()");
50: exit( 1 );
51: }
52: printf("received from "); sockaddr_in_print( &addr );
53: buff[rcount] = 0 ;
54: printf("%d bytes received. [%s] \n", rcount, buff );
55:
56: if( scount = sendto( s, buff, rcount, 0, &addr, addrlen )!= rcount )
57: {
58: perror("sendto()");
59: exit( 1 );
60: }
61: }
62: }
<以下省略>
----------------------------------------------------------------------
実行例。
サーバ側。サーバは、終了しないので、最後に、^C か Del を押して、割り込みを掛けて終了させる。
クライアント側(その1)。---------------------------------------------------------------------- % ./echo-server-udpmy port is sockaddr_in: 0.0.0.0:1231 received from sockaddr_in: 127.0.0.1:1453 6 bytes received. [hello] received from sockaddr_in: 130.158.86.225:1466 6 bytes received. [hello] received from sockaddr_in: 130.158.87.5:1714 6 bytes received. [hello] ^C %
----------------------------------------------------------------------
クライアント側(その2)。---------------------------------------------------------------------- % ./echo-client-udp localhost 1231my port is sockaddr_in: 0.0.0.0:1453 received from sockaddr_in: 127.0.0.1:1231 6 bytes received. [hello] % ./echo-client-udp orchid 1231
my port is sockaddr_in: 0.0.0.0:1466 received from sockaddr_in: 130.158.86.225:1231 6 bytes received. [hello] %
----------------------------------------------------------------------
---------------------------------------------------------------------- % ./echo-client-udp orchid 1231my port is sockaddr_in: 0.0.0.0:1714 received from sockaddr_in: 130.158.86.225:1231 6 bytes received. [hello] %
----------------------------------------------------------------------