Winsock、C++ を使用して、send()/recv()、TCP 接続でデータを送受信します。データが相手に届いたことを確認したいのですが、 recvでデータを受信した後 (if) に確認メッセージを返信することをお勧めします。
ここに 2 つの可能性があります。どちらに進むべきかアドバイスをお願いします。
sendが渡されたバッファのサイズを返す場合、データは少なくともワイヤの反対側のrecv関数に配信されていると想定します。「少なくとも」と言うとき、recvがそこで失敗したとしても(たとえば、バッファ不足などのために)、気にしないで、サーバーの一部の作業を適切に完了したことを確認したいだけです-データを完全に送信しました (つまり、データが他のマシンに到達しました)。
追加の確認応答を使用します。recvでデータを受信した後、受信したパケットの ID (送信された各データのヘッダーの一部) を送り返し、そのパケットの受信操作が成功したことを通知します。一定の間隔を置いてもそのような「確認メッセージ」を受信しない場合は、送信者関数から失敗コードを返します。
2 番目の回答の方が安全に見えますが、転送プロトコルが冗長である場合に複雑にしたくありません。また、TCP 接続について話していることにも注意してください (UDP よりも安全です)。
データが反対側のrecv関数に配信されたことを保証する他のメカニズム(おそらく他のAPI?おそらくWSARecv()/WSASend()の動作?)はありますか?
2 番目の方法をお勧めする場合は、recvをタイムアウト付きで使用して確認応答を受信できるようにするコード スニペットを教えてください。recvはブロッキング操作であるため、前回の送信試行が失敗した場合 (相手に通知されなかった場合) は永久にハングします。タイムアウトを指定してrecvを使用する簡単な方法はありますか(毎回個別のスレッドを作成することなく、おそらくすべての送信操作でやり過ぎになるでしょう)。
また、関数を送信するために渡すデータの量は非常に大きい (数メガバイト) 可能性があるため、「確認メッセージ」のタイムアウトを選択するにはどうすればよいですか? 大きなバッファを「分割」して、いくつかの送信呼び出しを使用する必要がありますか? かなり複雑になると思いますので、アドバイスお願いします!
編集: わかりました、あなたは TCP/IP スタックがそれを処理することを示唆しています(つまり、手動の承認は必要ありません)、これは私が MSDN ページで見つけたものです:この関数は、データが正常に送信されたことを示すだけです。」したがって、TCP メカニズムにデータ配信を保証する機能があるとしても、 send()関数やその他の Winsock 関数を介してそのステータス (成功かどうか) を取得することはできません。TCP層からステータスを取得する方法を知っていますか? 繰り返しますが、send()関数の戻り値が十分ではないようです!
================================================== ======
編集 2: OK、TCP プロトコルは何か問題が発生した場合のエラー処理を考慮しますが、Winsock のsend()関数はエラーを報告できないことに同意すると思います(単純に、実際のデータ送信が開始される前に返されるためです)。ネットワークドライバー)。ここで百万ドルの質問があります: Winsock のsend()関数は、少なくとも、現在のパケットが配信されるまで、他のパケットが相手に配信されないことを保証しますか? 言い換えれば、何らかのネットワーク障害で送信が失敗した場合 (しかし、send()呼び出しによって報告されない)、次のデータのチャンクでsend()関数の次の呼び出しの前にネットワーク障害が修正されます。前のパケット (失敗しましたが、によって報告されていません)send() ) は次のパケットの前に配信されますか? つまり、1 つの特定の send() 関数が「黙って」失敗し、後続の send() 呼び出しが成功しても最初のパケットが失われる可能性はありますか? 繰り返しますが、私は TCP レベルで話しているのではなく、Winsock API レベルで話しているのです!