満月 
 TOP > 講座 > ネットワーク講座 > 複数クライアント接続対応って何?



 

 複数クライアント接続対応って何?

 前述のサーバは、一つのクライアントの接続を受けて、そのクライアントに対して仕事をして、終了する、というあまり応用用途をイメージできない動作をしていましたが、ここでは、次のような仕様を持つアプリケーションを作ります。

・サーバはクライアントの接続を最低3つ許容する。

・サーバはいつでもクライアントから接続を受け付ける。

・サーバは一方のクライアントと接続中に他方のクライアントとも接続できる。

・サーバはクライアントから「今何時。」というメッセージを受信したら、「HH:MMです。」というメッセージを必ず返す。

・サーバはクライアントから「おーい、だれかいますか。」というメッセージを受信したら、送信してきたクライアント以外がいれば、そのクライアントに対して「おーい、だれかいますか。from ○」メッセージを送信する(○:サーバに接続してきた順に付与されるクライアント識別番号)。
クライアントはその「おーい、だれかいますか。from ○」というメッセージを受信したら、サーバに「はーい、います。to ○」を送信する。
そして、サーバはその「はーい、います。to ○」を受信したら、「はーい、△がいます。」(△:「はーい、います。to ○」を返してきたクライアントの識別番号)を「おーい、だれかいますか。」を送信してきたクライアントに返す。

・クライアントから切断されるまでは接続を維持する。

・クライアントは20秒周期で「今何時。」と「おーい、だれかいますか。」を交互に送信する。

 この仕様は汎用的な言い方をすると次のようなことを実現しているといえます。
接続、切断の自由

サーバが保持する情報の共有

サーバ経由の他クライアントとの通信


 では、サーバプログラムを見ていきましょう。

 クライアントからの接続要求受付(listen)までの処理は、すでに説明したサーバプログラムと同様です。
クライアントからの接続要求や、クライアントからのメッセージはサーバに発生するイベントと考えることができます。そして、今回の仕様では、これらのイベントが、いつ、いかなるときに発生するか、サーバにはわかりません。
 そのため、イベントが来るまで待機し、イベントが来たら処理する、という流れを繰り返しループ(while)の中で行います。
 イベントは「あるソケットにデータが到着したので読めるよ!」、「あるソケットに接続要求が到着したから受付可能だよ!」といったものになります。
 イベントが来るまでの待機に、selectを使っています。ソケットをfd_set型のデータ(readfds)に設定(FD_SET)し、さらにそのreadfdsをselectに設定することで、所望のイベントが到着するまで待機する、ということが実現できます。つまり、設定したソケットへの接続要求やデータの到着を、selectが監視してくれるようなイメージです。
 イベントが発生するとselectが戻り、readfdsにイベント発生したソケットを判別するための情報が格納されます。
 FD_ISSETマクロを使うことで、イベントが発生したソケットを知ることができるので、条件分岐させ、そのソケットに対する処理を行うことができます。


 では、クライアントプログラムを見ていきましょう。
 サーバへ接続するまでの処理は、すでに説明したクライアントプログラムと同様です。
 クライアントでは大きく二つのイベントが発生します。一つはサーバからのメッセージ到着、もう一つは20秒周期処理を実現するための「20秒経過しました」イベントです。サーバ同様、イベントが来るまで待機し、イベントが来たら処理する、という流れを繰り返しループ(while)の中で行います。
 サーバと比較するとselectの使い方が若干異なっています。それは第5引数にタイムアウト時間を設定していることです。ソケットに対するイベントが発生せず、第5引数に設定した時間が経過した場合、selectは0を返します。この機能を利用し、20秒周期を実現しています。
 timeGetTime()という関数を呼び出していますが、使用するにはwinmm.libというライブラリが必要です。前述のWinsock2ライブラリ(ws2_32.lib)と同じように追加してください。


 では、実際に動作させてみましょう。
まず、サーバを動作させます。

クライアントを3つ動作させます。
5秒ほど間隔を空けて、順に動作させると結果がわかりやすいです。
Visual C++上で同じプログラムを3つ動作させることはできないので、直接実行ファイルを3つダブルクリックして起動させます。実行ファイルはプロジェクトフォルダの配下にあります。
(下記、hogeというユーザでデフォルトのフォルダにmclientプロジェクトを作成した場合を例にしています。)

以下のような結果になるはずです。

サーバ


クライアント(0)


クライアント(1)


クライアント(2)

 いかがでしょうか? サーバが持つ情報の全クライアントでの共有、クライアント間のサーバ経由の通信ができていることがわかると思います。
 また、クライアントを一つ終了させて(右上の×で終了)、さらに新しく起動させてみたりしてみてください。クライアントの接続、切断が自由にいつでもできることがわかるかと思います。


 今回のプログラムは非常に小規模なものですので、それほど実感はないかもしれませんが、送受信しているデータがあまりイケてません。もっとシンプルにかつ保守しやすいように、「プロトコルって何?」で説明したような典型的な通信データへ最適化することができます。>>通信データ最適化って何?


 TOP
 Copyright (c) 2013 Studio Four Dimension. All Rights Reserved.