システム・プログラム
電子・情報工学系
新城 靖
<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)に注意し ないさい。