2013年5月14日火曜日

C言語でechoサーバーをつくる

echoサーバーとは、「クライアントが送ってきた文字列をそのまま返す」サーバーのことです
特に驚くこともない、面白みのないプログラムのように思えますが、この単純なプログラムにはシステムプログラミングやネットワークプログラミングに必要なエレメントが詰まっています(と、思います)

おおまかな流れとしては

  1. ソケット(クライアントからの接続を受け付ける窓口のようなもの)をつくる
  2. ソケットを初期化する
  3. クライアントが繋いでくるのを待ち、接続を確立する
  4. クライアントから送られてきた文字列データを読み取る
  5. 読み取ったデータと全く同じものをクライアントの標準出力へ書き込む
  6. 接続を終了する
といったかんじです

それでは、実際にソースコードを見てみましょう


解答例:echo_server.c

#include <sys/types.h>  
#include <sys/socket.h>
#include <sys/uio.h>  
#include <netinet/in.h>
#include <string.h> 
#include <stdio.h> 
#include <unistd.h> 

int
main()
{
int sockfd, acceptfd; 
int len; 
char buf[1024];
struct sockaddr_in server, client; 

/* ソケットを作る */
sockfd = socket(PF_INET, SOCK_STREAM, 0);

/* ソケットを初期化する */
memset(&server, 0, sizeof(server)); 
server.sin_family = PF_INET; 
server.sin_port   = htons(7000); 
server.sin_addr.s_addr = htonl(INADDR_ANY); 
bind(sockfd, (struct sockaddr *)&server, sizeof(struct sockaddr_in));

/* クライアントからの接続を待つ */
listen(sockfd, 5);

/* クライアントとの接続を確立する*/
memset(&client, 0, sizeof(client)); 
len = sizeof(client); 
acceptfd = accept(sockfd, (struct sockaddr*)&client, &len);

/* データを読み込む */
read (acceptfd, buf, sizeof(buf));
printf("accept data: %s\n", buf); 

/* データを書き込む */
write (acceptfd, buf, strlen(buf));

/* 接続を閉じる */
close(acceptfd); 
close(sockfd); 

return (0); 

}

ちなみに、インクルードファイルそれぞれが何のために必要かを示すと……


<sys/types.h>  → socket(), listen(), accept(), read(), write()
<sys/socket.h> → socket(), listen(), accept(), read(), write()
<sys/uio.h>, <unistd.h>   → read(), write()
<netinet/in.h> → struct sockaddr_in 
<string.h> → memset()

上記のようになります


動作を確認するには、上のソースコードをコンパイルして生成された実行ファイルを起動した後、同じマシン上で

telnet localhost 7000

と打ち込み、telnetを起動すれば、echoサーバーとの接続が確立されます

0 件のコメント:

コメントを投稿