11.22 標準モジュール SocketServer
SocketServer モジュールはネットワークサーバーを作成する作業を簡単にします。
4つの基本的なサーバークラスがあります。
TCPServerはインタネットTCPプロトコルを使用します。
それはクライアントとサーバーの間でデータの連続的なストリームを対象としています。
UDPServerはデータグラムを使用します。
それは情報の不連続なパケットで、送っている間に順序が乱れて到着したり、消失したりします。
ごく稀に使用されるUnixStreamServerとUnixDatagramServerクラスは似ています。
しかし、Unixのドメインソケットを使用します。それらは非Unix環境では利用できません。
ネットワークプログラムの詳細は W. Richard Steven著の UNIX Network Programmingとか
Ralph Davis著のWin32 Network Programmingのような本を参考にして下さい。
これら4つのクラスは要求synchronouslyを処理します。
次の要求が始まるまでにそれぞれの要求は完結していなくてはなりません。
それぞれの要求が完了するのに長い時間がかかるのは好ましくありません。
なぜなら、多くの計算が必要であったり、処理の遅いクライアントに多くのデータを返したりするからです。
解決策は、それぞれの要求を操作するプロセスやスレッドを分割して作成することです。
ForkingMixInとThreadingMixInが混ぜ合わされたクラスは
非同期的な動作に対応するのに使用されます。
サーバーを作成するにはいくつかの段階を踏む必要があります。
まず、BaseRequestHandlerクラスのサブクラスを要求を操作するクラスとして作成し、
そのhandle()メソッドを上書きします。このメソッドは入ってくる要求を処理します。
次に、サーバーのアドレスと要求操作クラスを引数といして、サーバークラスのインスタンスを作成します。
最後に、1つまたはたくさんの要求を処理するためにサーバーオブジェクトの
handle_request()またはserve_forever()メソッドを呼び出します。
サーバークラスには共通の外部メソッドと属性があります。
これらはネットワークプロセスを扱う上で特に問題はありません。
- fileno ()
-
サーバーが接続要求を受け付けているソケットの(整数型の)ファイル記述子を返します。
同じプロセスで複数のサーバーを監視できるように、
この関数はselect.select()に通常渡されます。
- handle_request ()
-
1つの要求を処理します。この間数では
get_request(), verify_request(), と process_request()の
メソッドを順番に呼び出します。
ユーザが用意した操作クラスの handle()メソッドで例外が発生したときは
サーバーの handle_error()メソッドが呼び出されます。
- serve_forever ()
-
要求を無限に処理し続けます。これは単純に無限ループでhandle_request()を呼び出します。
- address_family
-
サーバーのソケットが属するプロトコルの種類です。
handle_request()とsocket.AF_UNIXの2つが可能な値です。
- RequestHandlerClass
-
ユーザが用意した要求を操作するクラスです。
それぞれの要求に対してクラスのインスタンスが作成されます。
- server_address
-
サーバーが接続要求を受け付けるアドレスです。
アドレスのフォーマットはプロトコルの種類に依存して変わります。
詳細はソケットモジュールのドキュメントを参照して下さい。
インタネットのプロトコルでは、アドレスを与える文字列とポート番号の整数を含むタプルです。
たとえば、('127.0.0.1', 80)
- socket
-
ソケットオブジェクトです。サーバーは入ってくる要求をそこで受け付けています。
サーバークラスは以下のクラス変数を提供しています。
- request_queue_size
-
要求を受け付けるキューの大きさです。1つの要求の処理に長い時間がかかるとき、
サーバーがビジーである間に到着した要求は request_queue_sizeの大きさまで
キューにおかれます。
1度キューが一杯になると、クライアントからのさらなる要求は``Connection denied''エラーとなります。
デフォルト値は通常5ですが、これはサブクラスで上書きできます。
- socket_type
-
サーバーで使用されているソケットの型です。
socket.SOCK_STREAMとsocket.SOCK_DGRAMの2つが可能な値です。
TCPServerのように基本サーバークラスにサブクラスで上書きされた
いろいろなサーバーメソッドがあります。
これらのメソッドはサーバーオブジェクトを直接扱わない人には有用ではありません。
- finish_request ()
-
RequestHandlerClassのインスタンスを作成し、
handle()メソッドを呼び出して要求を本当に実行します。
- get_request ()
-
ソケットから要求を受け付け、
クライアントと通信するのに使用するnewソケットオブジェクトと
そのクライアントのアドレスを含む2つのタプルを返します。
- handle_error (request, client_address)
-
RequestHandlerClassのhandle()メソッドで例外が発生したとき、
この間数が呼ばれます。
デフォルトの動作は標準出力に実行結果を印字し、さらなる要求の操作を継続します。
- process_request (request, client_address)
-
RequestHandlerClassのインスタンスを作成するのにfinish_request() を呼び出します。
必要なら、要求を操作するため新しいプロセスやスレッドを作成出来ます。
tt>ForkingMixInとThreadingMixInクラスでこれはできます。
- server_activate ()
-
サーバーが動作するようにするためサーバーのコンストラクタによって呼び出されます。
無視されるかもしれません。
- server_bind ()
-
希望のアドレスとソケットで通信するためサーバーのコンストラクタによって呼び出されます。
無視されるかもしれません。
- verify_request (request, client_address)
-
ブール値を返します。値が真のとき、要求は実行され、値が偽のとき、要求は拒絶されました。
この関数はサーバーに対するアクセス制御をインプリメントすることを優先します。
デフォルトのインプリメントはいつも真が返されます。
要求の操作クラスは新しいhandle()メソッドを定義しなくてはなりません。
どんな種類のメソッドであっても優先できます。
新しいインスタンスはされぞれの要求に対して作成されます。
- finish ()
-
要求された全てのきれいに片づける動作を実行するためにhandle()メソッドのの後に呼び出します。
デフォルトのインプリメントでは何もしません。
setup()やhandle()で例外が発生するとこの関数は呼ばれないでしょう。
- handle ()
-
この関数は要求に答えるため、要求された全ての作業をします。
いくつかのインスタンスの属性はそれに有効です。
self.requestとしての要求、
self.client_requestとしてクライアントのアドレス、
self.serverとしてサーバーのインスタンス、
この場合サーバー毎の情報にアクセスする必要があります。
self.requestの型はデータグラムかストリームかのサービスで異なります。
ストリームサービスではself.requestはソケットオブジェクトです。
データグラムサービスではself.requestは文字列です。
しかし、これはStreamRequestHandlerとDatagramRequestHandlerが
混ぜ合わされた要求操作クラスを使用することで隠蔽されます。
self.rfileとself.wfileの属性を提供します。
self.rfileとself.wfileは
クライアントに要求されたデータを得たり、データを返したりするために
それぞれ読み、書きされます。
- setup ()
-
要求された初期化を実行するためにhandle()メソッドの前に呼び出します。
デフォルトのインプリメントはありません。
guido@python.org