システム・プログラム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] %
----------------------------------------------------------------------