2017-04-24 13 views
0

select()について理解できない点がいくつかあります。私はこの機能について読むように、私が見つけたそのディスカッションabout select()

select()関数は、あなたに彼らは(recvをされるのを待っているデータを持っている場合)dを参照するには同時にチェック 複数のソケットへの道を与えますか の場合は、ブロックせずにデータを送信したり、例外がある場合は が発生します。

1)私が理解した最初のことは、この機能がソケットを並行してチェックできるということでした。今度はsock1とsock2が正確に同じ時刻にパケットを受け取ったとします(sock1からのpacket1とsock2からのpacket2)、各パケットに対して何らかの処理が必要であると考えてください。並列のパケットの処理ですか?またはパケット1が処理され、パケット2が処理されますか?

int rv = select(maxSd, &readfds, NULL, NULL, NULL); 

if (rv == -1) { 
    perror("select"); // error occurred in select() 
} else if (rv == 0) { 
    printf("Timeout occurred! No data after 10.5 seconds.\n"); 
} else { 
    // one or both of the descriptors have data 
    if (FD_ISSET(sock1, &readfds)) { 
     printf("socket %i RECEIVED A PACKET \n", sock1); 
     recvlen = recvfrom(sock1, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr1, &addrlen1); 
     if (recvlen > 0) { 
      buf[recvlen] = 0; 
      printf("received message: \"%s\" (%d bytes)\n", buf, recvlen); 
      Packet mp; 
      mp.de_packet((unsigned char *)buf,recvlen); 
     } 
     else { 
      printf("uh oh - something went wrong!\n"); 

     } 
    } 
    if (FD_ISSET(sock2, &readfds)) { 
     printf("socket %i RECEIVED A PACKET \n", sock2); 
     recvlen2 = recvfrom(sock2, buf2, BUFSIZE, 0, (struct sockaddr *)&remaddr2, &addrlen2); 
     if (recvlen2 > 0) { 
      buf[recvlen2] = 0; 
      printf("received message2: \"%s\" (%d bytes)\n", buf2, recvlen2); 
      Packet mp; 
      mp.de_packet((unsigned char *)buf,recvlen); 
     } 
     else 
      printf("uh oh - something went wrong2!\n");       
    } 
} 

2)iは、ブロッキングと非ブロッキングに関連していることを選択についての他の疑い(以下のコードの例のために)。 ブロックの意味はなんですか?イベントが発生するまでプログラムがこの行で停止することを意味しますか? 私はブロックすることを避けるために、timeval tvまたはfcntl()を使用することが可能だと思います。もっと良い方法がありますか?選択の復帰時に、事前

答えて

1

おかげで、それが0または-1を返しませんでした提供、あなたのプログラムはreadfdsのすべての要素にループする必要があるとISSETが、それは対応して設定されているかどうかを評価しますソケットを処理する必要があります。したがって、sock1とsock2だけがreadfdsに設定されていると仮定すると、あなたのコードも正しいです。 のreadfdsのソケットの評価は、通常、同じスレッドによって順次行われます。次に、各ソケット内のパケットを順次または並列に処理することができます。 2つのソケットが完全に独立していることは明らかです。競合状態の可能性はありません。これはプログラムの仕方によって異なります。たとえば、ISSETがtrueを返すソケットごとに、そのスレッドを処理するスレッドを生成するか、ワーカースレッドのセットの作業キューに渡して、各スレッドを並列処理することができます。どんな種類の制限もありません。 readfsを並行してチェックすることさえできます。たとえば、スレッドのセットの下半分をチェックし、別のスレッドが上半分をチェックすることができます。これは単なる例です。ここでも、アプリケーションで競合条件を生成せずにプログラムを適切にプログラムすることに制限はありません。

ブロックまたは非ブロックの概念に関しては、選択は、セット内のソケットが処理するイベント(読み取り、書き込み、例外)またはタイムアウト(タイムアウト値を設定した場合)があるまで常にブロックされます。

また、ブロッキングソケットとノンブロッキングソケットについても説明します。ブロッキングソケットは、読み取りまたは書き込み操作でブロックできるソケットです。ブロッキングソケットは、読み込み準備ができていない限り読み込み操作でブロックされ、送信バッファがいっぱいで、バッファにバイトを書き込めない場合にブロックされます(これはSTREAMソケットで発生する可能性があります)。バイトを書き込むことができるまでブロックされます。何も読み込めない場合は、非ブロックソケットはブロックされません。関数readは-1を返し、エラー番号はEAGAINまたはEWOULDBLOCKに設定されます(http://man7.org/linux/man-pages/man2/read.2.html参照)。

選択は通常、ノンブロッキングソケットとともに使用されるため、スレッドは処理可能なソケットがあるまでブロックされます。これは、アプリケーションが常に非ブロッキングソケットをポーリングする必要があるため、効率的ではないため、これは良いことです。

選択はすべてのソケットを並行して処理しますが、イベントがあるかどうかをチェックするだけです。 selectは、パケットを処理しません。例に注意した場合、selectが返された後、アプリケーションはソケットからデータを読み取ります。これは、順次または並列で実行できます。

この説明がコンセプトを理解するのに役立つことを願っています。