1

TCP を使用して複数のスレーブ レプリカにデータをレプリケートする Linux 用の C で記述されたクライアント サーバー アプリケーションに取り組んでおり、一部のレプリカの予期しない一時的なシャットダウンに対処する方法を知りたいです (UNIX プロセスのクラッシュである可能性があります)。またはハードウェアの電源オフ)。

write() システムコールをカーネルに発行すると、正常に返されたということは、データがソケットにコピーされたことを意味しますが、受信側データを取得したことを意味するわけではありません。宛先の電源がオフになってから電源がオンになった場合は、データが失われた時点から (新しい TCP 接続を確立した後に) レプリカにデータを再送信する必要があります。

大量のデータを扱っていて、すでに送信したデータを保持していないとしましょう (つまり、write() システムコールが成功を返しました)。送信される保留中のデータのみを保持します。

レプリカが予期しないシャットダウンから回復し、再接続したとき、カーネルから、ソケットに書き込まれたが宛先ホストで「確認」されていないデータを取得するにはどうすればよいですか?

言い換えれば、TCP 接続の損失から回復し、停止した時点からクライアントとサーバー間の伝送を再確立するにはどうすればよいでしょうか?

4

3 に答える 3

2

標準のAPIを使用して必要な処理を実行する方法はありません。

解決策は、クライアントに定期的に受信および検証されたバイトの現在の合計をディスクに返送させ、送信されたが確認応答しないデータのバッファーをサーバーに保持させることです。その後、クライアントが再接続すると、最後の適切なカウントが送信され、サーバーは再送信を開始する場所を認識します。

于 2013-03-21T14:39:59.770 に答える
2

TCP の上に別のレベルの抽象化を追加する必要があります。すべてのデータが送信された後 (TCP は、データが無傷で順序どおりに到達することを保証します)、相手側のプロセスに独自の種類の ACK を独自の上位レベル プロトコルで送信させます (それが何であれ、" ACK\0"、"GOT\n" など)。反対側 (発信者) で、このデータを読み取ります。エラーなくうまくいけば、すべて問題ありません。エラーが発生した場合 -- タイプを確認してください。ECONNRESET が発生した場合は、リモート エンドが停止していることを意味します。このことから、それに応じて対応できます。再接続できるまで待ち、データ送信を最初からやり直してください。

于 2013-03-21T14:29:23.713 に答える
1

TCPはTCPに必要なシーケンス番号を処理しますが、アプリケーションレベルでそれらをあまり利用することはできません。

アプリケーションレベルでのシーケンス制御が必要です。

ここでのケースでは、送信したデータの各ブロックに番号を割り当てることができます。宛先は、受信した最後のブロック番号を永続的に追跡する必要があります。予期しないシャットダウンからの起動時に、宛先は最後に処理したブロック番号を通信する必要があり、そこから送信を開始します。

ソケットに書き込まれたが、宛先ホストで「ack」されていないデータをカーネルから取得するにはどうすればよいですか?

できたとしても、これでは十分ではありません。宛先ホストはデータをackした可能性がありますが、何らかの理由でackが失われたり、送信されなかったりする可能性がありますが、宛先アプリケーションはそのデータを正常に受信して処理できた可能性があります。したがって、この場合にTCPシーケンス番号を使用すると、データが重複することになります。

もう1つのケースは、TCPがデータのackを送り返し、宛先アプリケーションがそのデータを読み取ったときと同じように、ディスクに書き込む直前にクラッシュ/シャットダウンした場合です。したがって、データが失われることになります。

于 2013-03-21T14:47:50.153 に答える