サーバプログラムの解説
このプログラムはクライアントからの接続を受け付け、
入力された数値を加算して結果を返すサーバです。
socketにbindするアドレスとポートの情報の取得
gethostname(hostname,80);
thishost = gethostbyname(hostname);
bzero((char *)&me,sizeof(me));
me.sin_family=AF_INET;
me.sin_port = htons(LISTEN_PORT);
bcopy(thishost->h_addr,(char *)&me.sin_addr,thishost->h_length);
|
ここでは、このプログラムが実行されているマシンのホスト名を調べ、
それに基づいてIPアドレスを調べます。
そして、socketにbindするためにあとで使われるsockaddr_inの変数に
必要なIPアドレス、ポート、通信の種類をセットします。
struct hostentは/usr/include/netdb.hで、
struct sockaddr_inは/usr/include/netinet/in.hで、
定義されていますので、必要であれば確認してください。
listenするsocketの作成と設定
次に通信するsocketを作り、それにオプション設定と、
そのポートで使うアドレス、ポートまたプロトコルを設定します。
listen_socket = socket(AF_INET,SOCK_STREAM,0);
option = 1;
setsockopt(listen_socket,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
bind(listen_socket, &me,sizeof(me));
|
setsockopt()でソケットにSO_REUSEADDRのオプションを設定しているのは
ポートがすぐに再利用できるようにするためです。
TCPで通信をする場合、ソケットをクローズした後
TIME_WAITという状態を経て、再利用できるようになります。
これは、例えばコネクション型の通信を実現した
TCPには送信されたデータのACKが送られ、
ACKが来なければ再送するメカニズムがありますが、
相手がクローズしていればいつまでもACKは帰らないことになります。
このような種類の問題を無くすためにTIME_WAITの時間が設けられて
いるのです。詳しくは取り上げませんが、通常は問題はほとんど
起こらないので、このプログラムではすぐに再利用できるように
しています。(詳しく知りたければ SO_REUSEADDR と
TIME_WAITなどのキーワードでサーチエンジンで探してみてください)
bindではソケットにIPアドレスやポート番号、またプロトコルなどを
設定しています。
受付状態とし、接続を受け付ける
listen(listen_socket,1);
connected_socket = accept(listen_socket,NULL,NULL);
close(listen_socket);
|
- listen()
- 今後このポートへの接続要求があったら、こちらにつないでください
とOSに依頼します。
「交換手にこの内線番号に電話がかかったらこちらにつないでください」
と頼むのににています。
- accept()
- 電話がかかったという連絡がOSから来る待ち続けます。
OSは接続要求があったら、socketを作成し
「ここに相手とつながったsocketがありますので、
通信してください」とsocketを渡してくれます。
これ以降通信が可能となります。
- listenしているソケットのclose
- このポートへの接続要求はもう受け付けないことにします。
後はconnected_socketに対してwriteやreadを実行して、
相手と通信ができます。
|