[デーモン型サーバプログラム]
#include < stdio.h> char datavalue[256]; int GetLineFromPeer(int p ,char *line) { int i; for(i=0 ; ;) { if( read(p, line+i, 1) != 1 ) { continue; } else { i++; *(line+i) = (char)0; } if(((char)('¥n')) == (*(line+i-1))) return i; } } char *GetKeywordData(char *key) { FILE *fp; char buff[256]; if((FILE *)NULL == (fp = fopen(DATAFILE,"r"))) return (char *)NULL; for( ; ;) { char *p; char *pp; fgets(buff,256,fp); if(feof(fp)) break; if(ferror(fp)) break; if((char *)NULL == (p = strtok(buff,DELIMITS))) continue; if((char *)NULL == (pp = strtok((char *)NULL,DELIMITS))) continue; if( strcmp(p,key) == 0 ) { fclose(fp); strcpy(datavalue,pp); return datavalue; } } fclose(fp); return (char *)" "; } int main() { char RecvBuff[256]; int sockfd; int wait_socket; int writer_len; struct sockaddr_in r_addr; struct sockaddr_in w_addr; if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) { //IPソケットを生成 perror("socket"); exit(1); } bzero((char *) &r_addr, sizeof(r_addr)); r_addr.sin_family = PF_INET; r_addr.sin_addr.s_addr = htonl(INADDR_ANY); r_addr.sin_port = htons(5681); if (bind(sockfd, (struct sockaddr *)&r_addr, sizeof(r_addr)) < 0) { perror("bind"); exit(1); } if (listen(sockfd, 5) < 0) { perror("listen"); close(sockfd); exit(1); } if ((wait_socket = accept(sockfd,(struct sockaddr *)&w_addr, &writer_len)) < 0) { perror("accept"); exit(1); } for( ; ;) { char *p; char SendBuff[256]; char *pp; (void)GetLineFromPeer(wait_socket,RecvBuff); if(((char)('=')) == *(RecvBuff)) { exit(0); } if((char *)NULL != (p = strchr(RecvBuff,'='))) { *p = (char)0; if((char *)NULL == (pp = GetKeywordData(RecvBuff))) { sprintf(SendBuff,"%s=¥n",RecvBuff); } else { sprintf(SendBuff,"%s=%s¥n",RecvBuff,pp); (void)write(wait_socket,SendBuff,strlen(SendBuff)); } } } } |
<<実行結果>>
[nw0417:~/work/jikken2/tcpip] j04017% myclient Connected. Input Keyword = warning: this program uses gets(), which is unsafe. 123 Keyword = [123] / Data = [456] Input Keyword = abc Keyword = [xyz] / Data = [XYZ] Input Keyword = yama Keyword = [yama] / Data = [kawa] Input Keyword = shiro Keyword = [shiro] / Data = [kuro] Input Keyword = xxxx Keyword = [xxxx] / Data = [yyyy ] |
[inetdを使用するサーバプログラムとそうでないものの違い]
プログラムにinetdを使用した場合、接続はすべてinetdが行う。
つまり実験3のように、プログラムにbindやacceptやlistenなどを書く必要がない。しかしinetdには欠点もあり、クライアントが要求を送るたびにサーバが立ち上がったり、終了したりする。
よって頻繁なアクセスがある。inetdの場合、サーバの実行や終了に時間がかかるので時間がかかることがある。
[関数の説明]
・socket
この関数でソケットを作成する。この時点ではソケットに名前は付けられてはいない。
・bind この関数を利用することによって、ソケットに名前を付ける。つまりアドレスを与える。
・listen 最大要求数指定し、接続を待つ。このプログラムだと最大要求数は5となる。
・accept listenから接続要素をとりだして、接続が済んだソケットを新規に作成する。 そして、新しいファイルディスクリプタを割り当てて、そのファイルディスクリプタを返す。