コンテキスト: ネットワークの問題、停止、パイプの破損などが頻繁に発生するにもかかわらず、ほとんどの場合、かなり安定したクライアント サーバー アプリケーションを開発しています。ノンブロッキング ソケット、select()、および OpenSSL を使用して、アプリケーション レベルのハートビートを条件として、クラスター内の 1 つまたは複数のノード間でメッセージを配信します。メッセージはキューに入れられ、メッセージ全体が転送され、すべての SSL_write() が正常に返されるまで、キューから削除されません。私は各リレーションシップに対して 2 つのソケットを維持します。1 つは受信用で、もう 1 つは送信用です。これには理由があります。それは、読み取りよりも書き込みの方が接続の失敗 (非常に頻繁に) を検出する方がはるかに簡単だからです。クライアントが接続していて、既に接続している場合は、それを置き換えます。基本的、書き込みを実行するクライアントは、エラーを検出し、新しい接続を開始する責任があります (サーバー上の既存の (デッド) 読み取り接続を置き換えます)。これは、1つの例外を除いてうまくいきました。
残念ながら、私はメッセージを失っています。99.9% の確率で、メッセージは問題なく送信されます。しかし、ときどき送信しますが、数分間どちらの側でもエラーが検出されません...その後、ソケットでエラーが発生します。問題は、SSL_write が既に正常に返されたことです。
推測してみましょう: ブロックしていれば問題ありませんが、ブロックしていないので、リモート エンドでの読み取りを待ちません。TCP バッファーが収まる限り、パイプに何かを詰め込み続けます。そして、ソケットがだめになったとき、そのバッファ内のまだ配信されていないものを失いますか?
どうすればこれに対処できますか?アプリケーションレベルの ack は本当に必要ですか? (複雑なロスト ACK や重複したメッセージの複雑さの長い道のりをたどりたくありません) どのメッセージをロストしたかを知るエレガントな方法はありますか? または、配信されたことを確認するまでキューからの削除を遅らせる方法はありますか? (ACKなしで、どうやって?)
事前に助けてくれてありがとう。