2

ここ

http://marc.info/?l=openssl-users&m=124386218929227

それは次のように述べています

「...これが、任意のポートで可能な前方進行 (および WANT_READ を返す書き込み操作が前方進行を行った可能性がある!) を理解することが非常に重要な理由です!) すべてのポートですべての保留中の操作を再試行する必要があります.... "

それでSSL_read()、返さWANT_READれた が前進した可能性があることを理解するのは正しいですか (データを返さなかったとしても)?

3 つのノンブロッキング SSL ソケットを持つイベント ドリブンのシングル スレッド アプリがあります。各ソケットが接続を完了すると、WANT_READ. 私の理解では、ソケットが再び読み取りの準備ができるまでWANT_READ呼び出して待機することができるということです。select()

select()戻ると、ループは 3 つのソケットを経由し、それぞれを呼び出しますssl_read()

ソケット 1 で読み取りが返さWANT_READれ、データがないとします。ソケット 2 が何らかのデータを返しWANT_READ、それ以上読み取るものがなくなったときに戻り、ソケット 1 での読み取りがデータを返す可能性があるため、ある程度の進行があった可能性はありますか? しかし、ループはすでにソケット 1 の読み取りを行っているため、それは起こりません。

ループは 3 つのソケットを通過したため、そこで待機してハングします。このような状況が発生する可能性はありますか?

この場合、3 つのソケットすべてでこれ以上進行できないかどうかを確認するにはどうすればよいですか? たとえば、ループが通過するとします。

  • ソケット 1 が戻りますWANT_READ
  • 次に、ソケット 2 が何らかのデータを返しますWANT_READ(そして、ソケット 1 がデータを返すことができるように進行します) 。
  • ソケット 3 が戻りますWANT_READ

しかし、上記の引用に基づいて (進行中のすべての保留中の操作を再試行する必要がある場合)、すべてのソケットを再試行する必要があります。そのため、2 回目はループを実行します。

  • ソケット 1 がデータを返すようになり、次にWANT_READ
  • ソケット 2 が戻るWANT_READ
  • ソケット 3 がデータを返すようになりました (ソケット 1 での読み取りが、ソケット 3 がデータを返すのに十分なほど進行したため) WANT_READ

しかし、ソケット 3 での最後の読み取りが進行し、ソケット 2 が再びデータを返す場合はどうなるでしょうか? それで私の質問は(私の理解が正しければ)、これ以上進歩できないかどうかをどうやって知ることができますか?

編集1:

だから私が見ているのはこれです:

私のループは、client1 に接続されているすべてのソケット (たとえば、2 つのソケットがあるとします) を介して実行されます。

  • ソケット 1: ssl_read()WANT_READ を返します
  • ソケット 2:ssl_read()データをssl_read()返し、再びデータを返し、ssl_read()最後に WANT_READ を返します

次に、すべてのソケットが WANT_READ を返したので、待機しselect()ます。ただし、私のアプリは、クライアントが既に送信したデータをまだ待っています。クライアントに別の接続を開始させた場合 (オリジナルをアクティブにしたまま)、リターンを選択すると、次のように表示されます。

  • ソケット 1:ssl_read()データを返し、ssl_read()再び WANT_READ を返します
  • ソケット 2: ssl_read()WANT_READ を返します
  • ソケット 3(新規):ssl_read()データを返し、次に WANT_READ を返します。

そのため、select は新しい接続を検出し、すべてのアクティブな接続を通過するループを実行します。今回は、ソケット 3 の新しいデータに加えて、前回のソケット 1 からのデータが見つかりました。私の理論では、select() は最初は返されないということです。 1 はすでに到着し、準備ができており、ssl_read() を呼び出すのを待っています。しかし、前回 ssl_read を呼び出したとき、WANT_READ が返されました。

4

1 に答える 1

3

SSL_read()が負の値を返す場合は、 からエラー コードを取得する必要がありますSSL_get_error()。エラー コードがSSL_ERROR_WANT_READの場合は、そのソケットが読み取れるようになるまで (select()またはを使用して) (ネットワークからデータが到着するまで) 待機する必要があることを意味します。その場合は、そのソケットでpollSSL_read() を再試行する必要があります。SSL_ERROR_WANT_READを返したものだけで、持っているすべての SSL ソケットで再試行する必要はありません。(が返されたとき)で同様のことを行う必要があります。SSL_read()SSL_write()SSL_ERROR_WANT_WRITE

SSL_read()ただし、潜在的に返される可能性があり (SSL_get_error()つまり) SSL_ERROR_WANT_WRITESSL_write()返される可能性があることに注意してくださいSSL_ERROR_WANT_READ。これは、SSL がデータ以外に追加のメッセージを送受信する必要があるために発生する可能性があります (たとえば、データを送信するには、最初にメッセージを送信して応答を受信する必要があります)。

要約する:

  1. n = SSL_read()返却時:

    a) n > 0-->nバイトのデータを受信しました

    b) n < 0-->err = SSL_get_error()返された

    • SSL_ERROR_WANT_READ -->select()ソケットが読み取り可能になるまで、SSL_read()再度呼び出します
    • SSL_ERROR_WANT_WRITE -->select()ソケットが書き込み可能になるまでSSL_read()再度呼び出します

    c) n = 0--> if(SSL_get_shutdown(SSL*) & SSL_RECEIVED_SHUTDOWN): 反対側はクリーン シャットダウンを行いました。それ以外の場合、シャットダウンはクリーンではありませんでしたが、SSL 接続は閉じられています。ソケットを閉じることができます (SSL* オブジェクトも)

  2. n = SSL_write()返却時:

    a) n > 0-->nデータのバイトを送信しました

    b) n < 0-->err = SSL_get_error()返された

    • SSL_ERROR_WANT_READ -->select()ソケットが読み取り可能になるまで、SSL_write()再度呼び出します
    • SSL_ERROR_WANT_WRITE -->select()ソケットが書き込み可能になるまでSSL_write再度呼び出します

    c) n = 0--> if((err = SSL_get_error(SSL*,err)) == SSL_ERROR_ZERO_RETURN): 反対側はクリーン シャットダウンを行いました。それ以外の場合、シャットダウンはクリーンではありませんでしたが、SSL 接続は閉じられています。ソケットを閉じることができます (SSL* オブジェクトも)

それが役立つことを願っています。

于 2013-01-18T05:40:19.220 に答える