2

SSL を介して互いに通信する 2 つのアプリケーションがあります。クライアントは Windows マシンで実行され、サーバーは Linux ベースのアプリケーションです。クライアントは、起動時に大量のデータをサーバーに送信しています。データは、30 エントリを含む最大 4000 バイトのチャンクでサーバーに送信されます。約 50000 エントリを送信する必要があります。

その送信中に、サーバーはメッセージをクライアントに送信します。メッセージのサイズは最大 4000 バイトです。その後、クライアント側の SSL_write() は SSL_ERROR_WANT_WRITE のエラーを返し始めます。クライアントは 10 ミリ秒スリープし、まったく同じパラメータで SSL_write を再試行しますが、SSL_write は無限に失敗します。その後、中断します。新しいメッセージを送信しようとすると、以前に中止された同じメッセージを送信していないことを示すエラーが表示されます。

エラー:1409F07F:SSL ルーチン:SSL3_WRITE_PENDING:不正な書き込みの再試行」

サーバーはクライアントから 60 秒間応答がないため、最終的に接続を切断し、新しい接続を再確立します。これは単なる参考情報です。実際の問題は、SSL_write を再開させる方法です。

サーバーが受信中にリクエストを送信しない場合、問題は解決します。リクエストのサイズを 16K から 100 バイトに縮小すると、問題は発生しません。

SSL CTX MODE は、SSL_MODE_AUTO_RETRY および SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER に設定されます。

大量の情報を含む両側からの同時送信が原因でこの障害が発生する可能性があることを知っている人はいますか? これがサーバーからクライアントに送信されるサイズを制限する以外の制限である場合、それを防ぐために何ができますか? 私の懸念は、クライアントが何も送信していない場合、この問題を回避するために適用したスロットリングが無駄になることです。

クライアント側では、SSL_ERROR_PENDING_READ を受け取ったことがないにもかかわらず、書き込み中に読み取る必要があるかどうかを確認するために SSL_read を実行しようとしましたが、とにかくバッファはそれほど大きくありません。〜 1000 バイトのサイズ。

これに関する洞察をいただければ幸いです。

4

2 に答える 2

5

SSL_ERROR_WANT_WRITE - このエラーは、ソケット送信で EWOULDBLOCK または EAGAIN エラーが発生した場合にのみ、OpenSSL によって返されます (OpenSSL を使用していると想定しています)。ソケット送信は、送信側のバッファがいっぱいになると EWOUDLBLOCK エラーを返します。これは、サーバーがクライアントから送信されたメッセージを読み取っていないことを意味します。

したがって、本質的に、問題はサーバーに送信されたメッセージを読み取っていないサーバーにあります。サーバーをチェックして修正する必要があります。これにより、クライアントの問題が自動的に修正されます。

また、オプション「SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER」を設定したのはなぜですか? SSL は、次のレコードを送信する前に、送信しようとしているレコードが完全に送信されることを常に期待しています。

于 2012-12-07T05:24:58.273 に答える
3

クライアント側とサーバー側の両方のアプリで、読み取りと書き込みが 1 つのスレッドで処理されることがわかりました。上で説明したように、完全な嵐の場合、クライアントは書き込みに忙しい (ノンブロッキング)。次に、サーバーは、rx バッファーを処理する間に、独自のメッセージの大規模なセットを書き込むことを決定します。サーバー tx はブロッキング コールです。サーバーが書き込みを停止し、読み取りが不足し、バッファがいっぱいになり、デッドロック シナリオが発生します。

デフォルトの Windows バッファは 8k バイトなので、いっぱいになるのにそれほど時間はかかりません。

アーキテクチャは、両側で rx および tx 処理用の個別のスレッドが存在するようなものでなければなりません。短期的な/一時的な修正として、rx バッファーを増やし、tx 側のレートを制限して、デッドロックを防ぐことができます。

于 2012-12-07T16:31:34.197 に答える