6

サーバー アプリケーションがあるとします。接続は TCP 経由で、UNIX ソケットを使用します。

接続は非同期です。つまり、クライアントとサーバーのソケットはノンブロッキングです。

次の状況を想定してください: 状況によっては、サーバーが接続されたクライアントにデータを送信し、すぐに接続を閉じることを決定する場合があります: with を使用shutdownSHUT_RDWRます。

だから、私の質問は - クライアントが呼び出すときにrecv、(サーバーによって送信された) データを受け取ることが保証されていますか?

または、データを受信するには、サーバーの?recvの前に呼び出す必要があります。shutdownもしそうなら、データがクライアントによって受信されることを確認するために、何をすべきですか (より正確には、これをどのように行うべきですか)?

4

3 に答える 3

5

この動作は「setsockopt(SO_LINGER)」で制御できます。

SO_LINGERデータが存在する場合、閉じる機能が完了するのを待ちます。このオプションが有効で、close関数が呼び出されたときに未送信のデータが存在する場合、データが送信されるか接続がタイムアウトになるまで、close関数中に呼び出し元のアプリケーションがブロックされます。close関数は、呼び出し元をブロックせずに戻ります。このオプションは、ストリームソケットに対してのみ意味があります。

参照:

于 2012-08-09T18:38:41.737 に答える
5

このデータは言うまでもなく、データを受信するという保証はありませんが、ソケットが閉じられているときに保留中のデータは、他のすべてのデータと同じ保証の対象となります。尽力。

注: 「非同期」と「非ブロッキング」は 2 つの異なるものであり、同じものを表す 2 つの用語ではありません。

于 2012-08-09T22:26:58.490 に答える
4

ソケットへのデータの書き込みに成功すると、データはカーネルのバッファにあり、送信されて確認されるまでそこに留まります。シャットダウンによって、バッファリングされたデータが失われることはありません。ソケットを閉じても、バッファリングされたデータが失われることはありません。送信プロセスが終了しても、バッファリングされたデータが失われることはありません。

でバッファのサイズを観察できますnetstat。SendQ 列は、カーネルがまだ送信したいデータの量です。

クライアントがすべてを確認すると、ポートはサーバーから消えます。これは、クライアントがデータを読み取る前に発生する可能性があり、その場合はクライアントの RecvQ になります。基本的には何も心配する必要はありません。TCP ソケットへの書き込みが成功すると、すべてのコンポーネントは、送信側のソケットやプロセスに何が起こっても、データが無傷で宛先に到達するようにできる限りの努力をします。

サーバーがシャットダウンした後にクライアントが何かを送信しようとすると、クライアントは SIGPIPE を取得し、ソケットから利用可能なすべてのデータを読み取る前に終了する可能性があります。

于 2012-08-12T22:26:00.137 に答える