システム・プログラム 電子・情報工学系 新城 靖 <yas@is.tsukuba.ac.jp>
このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro-2000/2000-05-08
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.is.tsukuba.ac.jp/~yas/index-j.html
以下のプログラムは、echo サービスを利用するクライアントである。 "hello" という文字列を送り、それを受け取っている。---------------------------------------------------------------------- % egrep echo /etc/servicesecho 7/tcp echo 7/udp % hostname
adonis1 % telnet adonis1 7
Trying 130.158.86.1... Connected to adonis1. Escape character is '^]'. hello
hello aaa
aaa ^] telnet> quit
Connection closed. %
----------------------------------------------------------------------
---------------------------------------------------------------------- 1: 2: /* 3: echo-client.c -- 文字列を送受信するクライアント(TCP/IP版) 4: ~yas/syspro-2000/ipc/echo-client.c 5: $Header: /home/lab2/OS/yas/syspro-2000/ipc/RCS/echo-client.c,v 1.3 2000/05/07 10:31:57 yas Exp $ 6: <-- ipc/RCS/rdaytime.c,v 1.4 1997/06/02 22:27:08 yas Exp $ 7: Start: 1998/06/01 23:48:29 8: */ 9: #include <stdio.h> 10: #include <sys/types.h> /* socket() */ 11: #include <sys/socket.h> /* socket() */ 12: #include <netinet/in.h> /* struct sockaddr_in */ 13: #include <netdb.h> /* gethostbyname() */ 14: 15: extern int tcp_connect( char *hostname, int portno ); 16: extern int writen( int fd, char *buf, int nbytes ); 17: 18: main( int argc, char *argv[] ) 19: { 20: if( argc != 3 ) 21: { 22: fprintf( stdout,"Usage: %s host port\n",argv[0] ); 23: exit( -1 ); 24: } 25: echo_client( argv[1],atoi(argv[2]) ); 26: } 27: 28: echo_client( char *hostname, int portno ) 29: { 30: int sock ; 31: int rcount ; 32: int slen ; 33: char sbuf[BUFSIZ+1]; 34: char rbuf[BUFSIZ+1]; 35: 36: sock = tcp_connect( hostname, portno ); 37: if( sock<0 ) 38: exit( -1 ); 39: 40: strncpy( sbuf,"hello",BUFSIZ ); 41: sbuf[BUFSIZ] = 0 ; 42: slen = strlen( sbuf ) + 1 ; 43: printf("sending: %s\n",sbuf ); 44: if( writen( sock, sbuf, slen ) != slen ) 45: { 46: perror("write"); 47: exit( 1 ); 48: } 49: if( (rcount = read( sock, rbuf, BUFSIZ ))<0 ) 50: { 51: perror("read"); 52: exit( 1 ); 53: } 54: printf("received: ",rbuf ); fflush( stdout ); 55: writen( 1, rbuf, rcount ); 56: printf("\n"); 57: close( sock ); 58: } 59: 60: int tcp_connect( char *hostname, int portno ) 61: { 62: struct hostent *hostent ; 63: struct sockaddr_in addr ; 64: int addr_len ; 65: int s ; 66: 67: addr.sin_family = AF_INET ; 68: if( (hostent = gethostbyname( hostname )) == NULL ) 69: { 70: fprintf(stderr,"unknown host %s\n",hostname ); 71: return( -1 ); 72: } 73: bcopy( hostent->h_addr, &addr.sin_addr, hostent->h_length ); 74: addr.sin_port = htons( portno ); 75: if( (s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) 76: { 77: perror("socket"); 78: return( -1 ); 79: } 80: if( connect(s, &addr, sizeof(addr)) < 0 ) 81: { 82: perror( hostname ); 83: close( s ); 84: return( -1 ); 85: } 86: return( s ); 87: } 88: 89: /* See: UNIX Network Programming, SS.6.6, Utility routines */ 90: 91: int writen( int fd, char *buf, int nbytes ) 92: { 93: register int nleft, nwritten ; 94: 95: nleft = nbytes ; 96: while( nleft > 0 ) 97: { 98: nwritten = write( fd, buf, nleft ); 99: if( nwritten <= 0 ) 100: return( nwritten ); 101: nleft -= nwritten ; 102: buf += nwritten ; 103: } 104: return( nbytes - nleft ); 105: } ----------------------------------------------------------------------実行例。
TCP/IPのクライアント側のプログラムで大事なシステムコールとライブラリ関 数は、次の通りである。---------------------------------------------------------------------- % mkdir ipc% cd ipc
% cp ~yas/syspro-2000/ipc/echo-client.c .
% make echo-client
cc -c echo-client.c -o echo-client.o cc echo-client.o -o echo-client % ./echo-client
Usage: ./echo-client host port % ./echo-client adonis1 7
sending: hello received: hello % ./echo-client localhost 7
sending: hello received: hello %
----------------------------------------------------------------------
---------------------------------------------------------------------- struct hostent *gethostbyname(const char *name); struct hostent *gethostbyaddr(const char *addr, int len, int type); ----------------------------------------------------------------------/etc/services をアクセスするには、次のような関数を使う。
---------------------------------------------------------------------- struct servent *getservbyname(const char *name, const char *proto); struct servent *getservbyport(int port, const char *proto); ----------------------------------------------------------------------
次の通信プロトコルのクライアントを1つ以上作りなさい。(以下の項目には、 各プロトコルを説明したページへのリンクが埋め込まれている。)
まず、telnet で、これらのサーバに接続しなさい。そして、それぞれのプロ トコルに従って、要求を打ち込み、どのような結果が返ってくるかを調べなさ い。次に、telnet で行った要求の送信と結果の受信を行うようなプログラムを 作りなさい。このとき、必要なパラメタは、main() の引数から取りなさい。
注意。それぞれのプロトコルでは、接続先として次のホストを使いなさい。
プログラムをつくる時には、行末の扱い(CR-LF)に注意し ないさい。