4

Unix ソケット (O_NONBLOCK なし) を使用するクラス用のチャット クライアント サーバーを作成し、非同期 I/O を選択する必要があります。現時点では、サーバー上で、クライアントから 1024 バイトを読み取り、直接処理しています。

たとえば、メッセージの場合、MSG <msg>(メッセージを送信するクライアントを表す) の形式のコマンドを受け取ります。接続されているクライアントのすべてのソケットを調べて、それらにメッセージを書き込みます。

sendこのアプローチは実際には機能しますが、ソケットバッファーがいっぱいで、フラグ O_NONBLOCK がソケットに設定されていない場合にブロックできることを最近読んでわかりました。

この問題は、クライアントが何らかの理由 (クラッシュ、バグなど) で読み取れない場合に発生する可能性があると思います。これは、このクライアントが再度読み取るまで基本的にブロックされるため、サーバーにとって重要です。

だからここに私の質問があります:

ソケットバッファがいっぱいの場合にブロックへの送信を避けるために、潜在的にブロックしているソケットの正しいアプローチは何ですか?

私は現在、ソケットで読み取るものがあるかどうかを確認するためだけに選択を使用していますが、特定のソケットにも書き込むことができるかどうかを確認するためにも使用する必要がありますか? また、選択が返されたときに読み書きできるバイト数を知ることはできますか? たとえば、このソケットに書き込むことができることを select が「伝える」場合、このソケットへの書き込みが実際にブロックされる前に、最大で何バイト書き込むことができるかをどのように知ることができますか?

ありがとう。

4

3 に答える 3

0

このアプローチは実際には機能しますが、最近、送信者を読んで、ソケットバッファーがいっぱいで、フラグ O_NONBLOCK がソケットに設定されていない場合にブロックできることがわかりました。

これが select を使用する理由ですが、次のように信頼性はありませんman select

Linux では、select() がソケット ファイル記述子を「読み取り準備完了」と報告する場合がありますが、その後の読み取りはブロックされます。これは、たとえば、データが到着したが、検査時に間違ったチェックサムがあり、破棄された場合に発生する可能性があります。ファイル記述子が誤って準備完了と報告される状況が他にもある可能性があります。したがって、ブロックしてはならないソケットでは O_NONBLOCK を使用する方が安全かもしれません。

于 2013-08-05T10:14:52.223 に答える
0

恐ろしいかもしれません。NONBLOCK モードに移行せず、select() を呼び出すと、特定のタイムアウト値でプロセスが内部的にスリープ状態になります。つまり、fd はその特定の期間ブロックされます。

于 2013-04-25T10:59:33.000 に答える