3

データを送信したいブロッキングSSLBIOオブジェクトがあります。問題は、接続がリモート側で閉じられており、読み取りを実行するまでそれを見つけることができないことです(BIO_writeはエラーを返しません)。ただし、ブロックしたくないので、送信する前に読むことができません。最後に、データの送信を担当するコードと読み取りを担当するコードは別々です。つまり、失敗した読み取りは別の送信をトリガーできません。これを修正するにはどうすればよいですか?

4

1 に答える 1

1

「閉」状態には 2 種類あり、「半閉」状態と呼ばれます。それらは主に、ソケットの一方または他方がアプリケーション データを送信するかどうかに関係しています。呼び出しが 0 を返す場合、recv実際には、受信するデータがこれ以上ないことを通知しています。ただし、呼び出しがor などsendの他の種類のエラーを通知しない限り、データを送信しても問題ありません (winsock でこれらに相当する Windows が何であるかはわかりませんが、それらがあることは知っています)。がエラーを返さない場合は、ソケットの反対側がまだデータを受け入れているためです。EPIPEECONNRESETSSL_write

このrecv呼び出しにより、「no more data」状態のノンブロッキング チェックが可能になり、次のように実行できます。

char c;
int r = recv(sock, &c, 1, MSG_DONTWAIT|MSG_PEEK);

rがの場合0、ソケットは相手側から保留中のデータがないという指示を受け取りました。それ以外の場合、呼び出しは11 バイトのデータ ( のために入力バッファにまだあるMSG_PEEK)、または-1. errnoEAGAIN( のために可能である) である場合、MSG_DONTWAITエラーはありません。他のerrno値を参照する必要がありますが、ソケットが無効な状態にあり、閉じる必要があることを示している可能性があります。

ソケットが閉じられる前に、OpenSSL アプリケーションはSSL_shutdown1 が返されたことを確認する必要があります。次に、オブジェクトが破棄されcloseた後にソケットで が発生します ( で)。これが意味することは、アプリケーションが何か異常を行わない限り、OpenSSL を使用するソケットの両側で戻りが確認され、両側で安全に接続を閉じることができるということです。SSLSSL_freeSSL_shutdown1

SSLコンテキストのシャットダウン状態を確認したい場合は、 を使用できます。これは、相手側がシーケンスSSL_get_shutdownを開始したかどうかを報告します。SSL_shutdown

于 2012-06-10T01:28:02.977 に答える