このモジュールは、非同期ソケットサービスのクライアント・サーバを開発する ための基盤として使われます。
CPUが一つしかない場合、プログラムが``二つのことを同時に''実行する方法は 二つしかありません。もっとも簡単で一般的なのはマルチスレッドを利用する方 法ですが、これとはまったく異なるテクニックで、一つのスレッドだけでマルチ スレッドと同じような効果を得られるテクニックがあります。このテクニックは I/O処理が中心である場合にのみ有効で、CPU負荷の高いプログラムでは効果が無 く、この場合にはプリエンプティブなスケジューリングが可能なスレッドが有効 でしょう。しかし、多くの場合、ネットワークサーバではCPU負荷よりはIO負荷 が問題となります。
もしOSのI/Oライブラリがシステムコール select() をサポートし ている場合(ほとんどの場合はサポートされている)、I/O処理は``バックグラ ウンド''で実行し、その間に他の処理を実行すれば、複数の通信チャネルを同時 にこなすことができます。一見、この戦略は奇妙で複雑に思えるかもしれません が、いろいろな面でマルチスレッドよりも理解しやすく、制御も容易です。 asyncoreは多くの複雑な問題を解決済みなので、洗練され、パフォー マンスにも優れたネットワークサーバとクライアントを簡単に開発することがで きます。とくに、asynchatのような、対話型のアプリケーションや プロトコルには非常に有効でしょう。
基本的には、この二つのモジュールを使う場合は一つ以上のネットワーク チャネルをasyncore.dispatcherクラス、または asynchat.async_chatのインスタンスとして作成します。作成されたチ ャネルはグローバルマップに登録され、loop()関数で参照されま す。loop()には、専用のマップを渡す事も可能です。
チャネルを生成後、loop()を呼び出すとチャネル処理が開始し、最 後のチャネル(非同期処理中にマップに追加されたチャネルを含む)が閉じるま で継続します。
[timeout[, use_poll[, map[,count]]]]) |
False
です。引数mapには、監視するチャネルをアイテム
として格納した辞書を指定します。mapが省略された場合、グローバル
なマップが使用される。グローバルなマップは、チャネルクラスの
__init__()メソッドが呼び出されたときに自動的に更新されま
す。- この仕組みを利用するのであれば、チャネルクラスの
__init__()はオーバライドするのではなく、拡張しなければなりま
せん。
) |
dispatcherクラスには二つのクラス属性があり、パフォーマンス向上 やメモリの削減のために更新する事ができます。
4096
)
4096
)
非同期ループ内で低レベルイベントが発生した場合、発生のタイミングやコネ クションの状態から特定の高レベルイベントへと置き換えることができます。 例えばソケットを他のホストに接続する場合、最初の書き込み可能イベントが 発生すれば接続が完了した事が分かります(この時点で、ソケットへの書き込 みは成功すると考えられる)。このように判定できる高レベルイベントを以下 に示します:
イベント | 解説 |
---|---|
handle_connect() |
最初にwriteイベントが発生した時 |
handle_close() |
読み込み可能なデータなしでreadイベントが発生 した時 |
handle_accept() |
listen中のソケットでreadイベントが発生した時 |
非同期処理中、マップに登録されたチャネルのreadable()メソッド とwritable()メソッドが呼び出され、select()か poll()でread/writeイベントを検出するリストに登録するか否か を判定します。
このようにして、チャネルでは低レベルなソケットイベントの種類より多くの種 類のイベントを検出する事ができます。以下にあげるイベントは、サブクラスで オーバライドすることが可能です:
) |
) |
def handle_write(self): sent = self.send(self.buffer) self.buffer = self.buffer[sent:]
) |
) |
) |
) |
) |
) |
True
を返し、readイベントの発
生を監視します。
) |
True
を返し、writeイベントの
発生を監視します。
さらに、チャネルにはソケットのメソッドとほぼ同じメソッドがあり、チャネル はソケットのメソッドの多くを委譲・拡張しており、ソケットとほぼ同じメソッ ドを持っています。
family, type) |
address) |
data) |
buffer_size) |
backlog) |
address) |
) |
(conn, address)
のペアで、connはデータの送受信
を行うソケットオブジェクト、addressは接続先ソケットがバインドさ
れているアドレスです。
) |