ITインフラ技術の実験室ITインフラ技術の実験室Linuxを中心に、仮想化やネットワーク、Windowsまで、ITインフラ技術に関するノウハウを幅広く紹介します。その1)で説明したサーバでのシステムコールの使用順序は以下の通りです。closeこの流れでプログラムを組むと以下のようになります。;}}まずacceptで処理がブロックされます。クライアントからの接続があると処理が先に進み、次にrecv/sendにてループ処理を行います。recv/sendが終了するまでforループが続くため、新規クライアントは接続できません。ディスクリプタをノンブロッキングにしてrecv/sendする方法もありますが、forループが無限ループとなりCPUを激しく消費することになります。あるクライアントと送受信を行う間も別のクライアントから接続できるようにするには、IOの多重化が必要になります。多重化には以下の3つの方式があります。送受信の連携がやや面倒デッドロックなどの問題を引き起こしやすい終了処理の考慮が面倒プログラム異常時に全体が影響を受ける各処理の終了時のリソース解放に注意が必要1プロセスのリソース制限を受ける本ページでは、上記のうち、方式1:シングルプロセスシングルスレッドについて紹介します。方式3についてはLinuxネットワークプログラミング(マルチスレッドで多重化)を見て下さい。方式1にはselect()、poll()、EPOLL()がありますが、一つずつ取り上げると長くなるため、select()のみ取り上げます。無限ループの中で上記システムコールを呼び出し新規クライアントからの接続、または既存クライアントからの受信を待ち受けるという基本的な使い方は三つとも同じです。簡単にselect()との違いを挙げておきますと、poll()は監視中のディスクリプタの変化を指定できる分、select()よりも細かいコントロールができる点で優れています。EPOLL()も基本的にpoll()と同じ優位性がありますが、数千コネクションが接続された際にselect(),poll()で問題になるパフォーマンスの問題を改善する工夫がされている点で3方式のなかで最も優れた方式です。EPOLL()はLinuxでしか使用できないため、移植性には難有りです。詳細な説明がありますので、気になる方はぜひ読んでみて下さい。シングルプロセス、シングルスレッド(select())についてselect()はaccept()やrecv()同様、処理をブロックしますが、複数のディスクリプタを同時に見張ることができるため、クライアントからの新規接続や接続中クライアントからの受信など、記述子の変化があった場合にどのような変化かに関わらず処理を先に進められます。各ディスクリプタに変化があるまでブロックするため、CPUパワーを無駄に消費することもありません。読みが可能になったら教えて欲しい記述子群。接続待ちソケットもこれに含める。書きが可能になったら教えて欲しい記述子群。エラーが起きたら教えて欲しい記述子群。見張るべき記述子のうち最大の値のものに1を足した値を指定する。ここで指定した時間が経過するとブロックが解除される。NULLを指定すると監視対象がレディになるまで待ち続ける。返り値が-1の場合はエラー。0の場合はタイムアウト。1以上の場合はレディ状態の記述子が1つ以上ある場合です。サーバ用途であればnfdsとreadfdsのみ指定し、残りはNULLで事足りることが多いです。サーバでのシステムコールの使用順序は以下の通りです。socket→bind→listen→select→accept(socket→bind→listen→select)→recv→shutdown→closeselectで変化を検知した記述子が接続待ちソケット(通常は3)であればaccept、それ以外であればすでに接続済みクライアントからのデータ受信であるため、処理を分岐します。selectと共に使用することになるシステムコールも合わせて紹介します。fdsetに指定されたfd_set型のデータの全ビットを0にする。fdをfdsetに追加する。fdsetにfdが含まれていれば非0を返し、含まれていなければ0を返す。上記システムコールの典型的な使い方は以下の通りです。FD_ZEROでreadfdsを0にする。FD_SETで監視する記述子をセットする。select()を呼び出す。FD_ISSETでどの記述子が変化したのかを調べて処理を分岐させる。ソース例を以下に載せるので、これまでの説明と見比べてみてください。socket→bind→listenについては割愛しますが、変数socが接続待ちソケットと仮定します。ソースを分かりやすくするため、接続できるクライアント数を3つまでと仮定します。child[0]、child[1]、child[2]は接続中クライアントがいれば記述子が入る。select()の第一引数に使用。recv処理などをここで実施。}}次回以降でマルチプロセス、マルチスレッドを紹介します。コメントをキャンセルメールアドレスが公開されることはありません。