13

私は、UDPを使用して、Pythonでスレッド化された非同期ネットワーキングの実験を行っています。

ポーリングとPythonモジュールの選択について理解したいのですが、C /C++で使用したことはありません。

それらは何のためのものですか?ちょっとした選択はわかりますが、リソースを見ているとブロックされますか?ポーリングの目的は何ですか?

4

3 に答える 3

16

さて、一度に1つの質問。

それらは何のためですか?

単純なソケットサーバースケルトンは次のとおりです。

s_sock = socket.socket()
s_sock.bind()
s_sock.listen()

while True:
    c_sock, c_addr = s_sock.accept()
    process_client_sock(c_sock, c_addr)

サーバーはループしてクライアントからの接続を受け入れ、そのプロセス関数を呼び出してクライアントソケットと通信します。ここに問題があります:process_client_sock時間がかかるか、ループが含まれている可能性があります(これはよくあることです)

def process_client_sock(c_sock, c_addr):
    while True:
        receive_or_send_data(c_sock)

この場合、サーバーはそれ以上の接続を受け入れることができません。

簡単な解決策は、マルチプロセスまたはマルチスレッドを使用し、要求を処理するための新しいスレッドを作成するだけで、メインループは新しい接続をリッスンし続けます。

s_sock = socket.socket()
s_sock.bind()
s_sock.listen()

while True:
    c_sock, c_addr = s_sock.accept()
    thread = Thread(target=process_client_sock, args=(c_sock, c_addr))
    thread.start()

これはもちろん機能しますが、パフォーマンスを考慮すると十分ではありません。新しいプロセス/スレッドは余分なCPUとメモリを必要とするため、サーバーがアイドル状態でない場合、数千の接続が発生する可能性があります。

したがってselectpollシステムコールはこの問題を解決しようとします。ファイル記述子のセットをselect指定し、fdが読み取り/書き込み/または例外が発生した場合に通知するように指示します。

リソースを監視している間、it(select)はブロックしますか?

はい、またはいいえは、渡したパラメーターによって異なります。

select manページにあるように、struct timevalパラメータを取得します

int select(int nfds, fd_set *readfds, fd_set *writefds,
       fd_set *exceptfds, struct timeval *timeout);

struct timeval {
long    tv_sec;         /* seconds */
long    tv_usec;        /* microseconds */
};

3つのケースがあります:

  1. timeout.tv_sec==0およびtimeout.tv_usec=0

    ブロッキングなし、すぐに戻る

  2. タイムアウト==NULL

    ファイル記述子の準備ができるまで、永久にブロックします。

  3. タイムアウトは正常です

    一定の時間待機します。それでも使用可能なファイル記述子がない場合は、タイムアウトして戻ります。

ポーリングの目的は何ですか?

簡単に言えば、ポーリングはIOを待機しているときに他の作業のためにCPUを解放します

これは、次のような単純な事実に基づいています。

  1. CPUはIOよりもはるかに高速です
  2. ほとんどの場合、CPUはアイドル状態になるため、IOの待機は時間の無駄です。

それが役に立てば幸い。

于 2015-03-28T08:58:24.307 に答える
12

readまたはの場合recv、1つの接続のみを待機しています。複数の接続がある場合は、複数のプロセスまたはスレッドを作成する必要があり、システムリソースが無駄になります。

selectまたはpollまたはを使用epollすると、1つのスレッドのみで複数の接続を監視し、それらのいずれかにデータが利用可能になったときに通知を受け取り、対応する接続​​でreadまたはを呼び出すことができます。recv

引数に応じて、無限にブロックするか、一定時間ブロックするか、まったくブロックしない場合があります。

于 2011-09-18T08:39:19.047 に答える
2

select()は、ソケットの3つのリストを取り込んで、3つの条件(読み取り、書き込み、エラー)をチェックし、それらの条件で実際に処理する準備ができているソケットのリスト(通常は短く、多くの場合空)を返します。

s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind((Local_IP, Port1))
s1.listen(5)

s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.bind((Local_IP, Port2))
s2.listen(5)

sockets_that_might_be_ready_to_read = [s1,s2]
sockets_that_might_be_ready_to_write_to = [s1,s2]
sockets_that_might_have_errors = [s1,s2]


([ready_to_read], [ready_to_write], [has_errors])  = 
       select.select([sockets_that_might_be_ready_to_read],
                     [sockets_that_might_be_ready_to_write_to], 
                     [sockets_that_might_have_errors],            timeout)


for sock in ready_to_read:
    c,a = sock.accept()
    data = sock.recv(128)
    ...
for sock in ready_to_write:
    #process writes
    ...
for sock in has_errors:
    #process errors

したがって、タイムアウト秒待機後にソケットが接続を試行しなかった場合、リストready_to_readは空になります-その時点で、accept()とrecv()がブロックされるかどうかは関係ありません-空の場合は呼び出されませんリスト....

ソケットが読み取る準備ができている場合、データが含まれているので、それもブロックされません。

于 2013-12-13T19:46:12.917 に答える