echoサービスのクライアント

システム・プログラム

                                       電子・情報工学系
                                       新城 靖
                                       <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サービスのクライアント

TCP/IP のポート番号 7 では、送られてきた文字をそのまま 返すサービスを提供している。

----------------------------------------------------------------------
% egrep echo /etc/services  [←]
echo            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.
% []
----------------------------------------------------------------------
以下のプログラムは、echo サービスを利用するクライアントである。 "hello" という文字列を送り、それを受け取っている。

----------------------------------------------------------------------
   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:	}
----------------------------------------------------------------------

実行例。

----------------------------------------------------------------------
% 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
% []
----------------------------------------------------------------------
TCP/IPのクライアント側のプログラムで大事なシステムコールとライブラリ関 数は、次の通りである。 ホスト名から IP アドレスを調べるには、gethostbyname() を使う。これは、 hostent 構造体を返す。内部的には、/etc/hosts というファイルや, NIS の hosts マップ, DNSが調べられる。
----------------------------------------------------------------------
     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);
----------------------------------------------------------------------

■練習問題と課題

★練習問題47 getservbyname()の利用

上の echo-client.c を、getservbyname() を使うように書き換えなさい。

★練習問題48 TCP/IPクライアントの作成

次の通信プロトコルのクライアントを1つ以上作りなさい。(以下の項目には、 各プロトコルを説明したページへのリンクが埋め込まれている。)

まず、telnet で、これらのサーバに接続しなさい。そして、それぞれのプロ トコルに従って、要求を打ち込み、どのような結果が返ってくるかを調べなさ い。

次に、telnet で行った要求の送信と結果の受信を行うようなプログラムを 作りなさい。このとき、必要なパラメタは、main() の引数から取りなさい。

注意。それぞれのプロトコルでは、接続先として次のホストを使いなさい。

HTTP
www.jks.is.tsukuba.ac.jp
finger
adonis-serv, localhost
NNTP
jks-news ($NNTPSERVER)
SMTP
adonis-serv, localhost

プログラムをつくる時には、行末の扱い(CR-LF)に注意し ないさい。


↑[もどる] ←[5月01日] ・[5月08日] →[5月15日] [課題]
Last updated: 2000/05/07 20:39:03
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>