2013-12-09 38 views
7

私はPythonでネットワーク指向のアプリケーションを書くことに取り組んでいます。以前はブロッキングソケットを使用していましたが、要件とコンセプトをよく理解した上で、ノンブロッキングソケットとイベントドリブンサーバーを使用してアプリケーションを作成したいと考えています。Pythonのselectモジュールのselect()関数はどのように機能しますか?

私は、Pythonのselectモジュールの関数を使用して、どのソケットが私たちに興味を持っているかを便利に理解することを理解します。それに向けて、私は基本的にイベント駆動型サーバーの例をいくつめくっしようとしていたと私はこの1つに遭遇していた:私は理解していないようでした部品は以下の通りです

""" 
An echo server that uses select to handle multiple clients at a time. 
Entering any line of input at the terminal will exit the server. 
""" 

import select 
import socket 
import sys 

host = '' 
port = 50000 
backlog = 5 
size = 1024 
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
server.bind((host,port)) 
server.listen(backlog) 
input = [server,sys.stdin] 
running = 1 
while running: 
    inputready,outputready,exceptready = select.select(input,[],[]) 

    for s in inputready: 

     if s == server: 
      # handle the server socket 
      client, address = server.accept() 
      input.append(client) 

     elif s == sys.stdin: 
      # handle standard input 
      junk = sys.stdin.readline() 
      running = 0 

     else: 
      # handle all other sockets 
      data = s.recv(size) 
      if data: 
       s.send(data) 
      else: 
       s.close() 
       input.remove(s) 
server.close() 

コードスニペットinputready,outputready,exceptready = select.select(input,[],[])では、select()関数は、入力、出力、例外条件のために待機可能オブジェクトの空リストを3つ返すと考えています。したがって、select()関数の最初の引数は、サーバーソケットとstdinを含むリストです。しかし、私は混乱に直面しているコードのブロックelseです。

inputreadyソケットのリストをループしているので、select()関数が読み込み準備の整ったクライアントソケットを選択することは明らかです。しかし、recv()を使用してデータを読み取り、ソケットが実際にデータを送信したことを確認したら、それをクライアントにエコーします。私の質問は、select()関数呼び出しの2番目の引数として渡されたリストにこのソケットを追加せずにこのソケットに書き込むことができますか?意味、どのように私たちはselect()を書き込み可能なソケットとして '登録'せずに、新しいソケットにsend()を直接呼び出すことができますか?

また、読み込み準備が整っているソケット(この場合はinputready)上でのみループするのはなぜですか?書き込まれる準備ができているソケットを見るために、outputreadyリストでさえもループする必要はありませんか? 明らかに、私はここに何かを見逃しています。

誰かがもう少し詳細にファッションを説明できるのであれば、select()の機能が役立つか、または良い文書を指し示すことができます。

ありがとうございます。

+2

私はあなたがサンプルコードの詳細によって混同されていると思います。書き込む準備ができているのを待たずにソケットで送信することは問題ありませんが、送信バッファがいっぱいであればブロックされます。サンプルコードでこのケースを無視しています。 'select'マニュアルページは、それを囲む薄いラッパーなので、あなたは見たいかもしれません。 http://docs.python.org/2/library/select.html –

答えて

1

コードスニペットは単なる例に過ぎないので、網羅的ではありません。あなたが選択したことがあなたに準備ができていると言っていない場合でも、すべてのソケットに自由に書き込んで読むことができます。しかし、もちろん、これを行うとsend()がブロックされないことを確かめることはできません。 はい、書き込み操作にもselectを使用することをお勧めします。 同様の目的を持った他の多くの機能があります。多くの場合、選択したほうが優れています(たとえばepoll)。ただし、すべてのプラットフォームで利用できるわけではありません。 selectに関する情報、epoll &その他の機能は、Linuxのマニュアルページにあります。

しかしPythonで多くの接続を処理するために使用される多くの素敵なライブラリがあり、これらのいくつかは以下のとおりです。 Twistedgevent

+0

ありがとうございます。Twistedなどの助けを借りずにアプリをコーディングするのは、うまくいく仕事でしょうか? – gravetii

+1

あなたのニーズによって異なります。例えば、geventのようなlibは、現在のプラットフォーム(Linuxの場合はepoll、FreeBSDの場合はkqueue)上で利用できる最適なツールを選択することができます。あなた自身で行うこともできますが、プロジェクトが実験以上のものであり、最高のパフォーマンスが本当に必要な場合は、おそらくgeventやTwistedのような広く使用されテストされているツールに頼るほうがよいでしょう。 これらのライブラリの最適化のレベルに達することは容易ではありません。 – smeso

関連する問題