TCP ウィンドウは、接続上のピア間のフロー制御に使用されます。各 ACK パケットで、ホストは「ウィンドウ サイズ」フィールドを送信します。このフィールドは、ホストがいっぱいになる前に受信できるデータのバイト数を示します。送信者は、その量を超えるデータを送信することは想定されていません。
クライアントが十分な速さでデータを受信していない場合、ウィンドウがいっぱいになることがあります。つまり、アプリケーションがソケットからの読み取り以外の処理を行っていない間に、TCP バッファがいっぱいになる可能性があります。その場合、クライアントは「window full」ビットが設定された ACK パケットを送信します。その時点で、サーバーはデータの送信を停止するはずです。フル ウィンドウのマシンに送信されたパケットは、確認応答されません。(これにより、行儀の悪い送信者は再送信します。行儀の良い送信者は、送信データをバッファリングするだけです。送信側のバッファもいっぱいになると、送信側のアプリは、ソケットにさらにデータを書き込もうとするとブロックされます。 !)
これは TCP ストールです。これはさまざまな理由で発生する可能性がありますが、最終的には、受信者が読み取る速度よりも送信者が高速に送信していることを意味します。
受信側のアプリがソケットからの読み取りに戻ると、バッファリングされたデータの一部が排出され、スペースが解放されます。次に、受信者は「ウィンドウ更新」パケットを送信して、送信できるデータ量を送信者に伝えます。送信者はバッファリングされたデータの送信を開始し、トラフィックは正常に流れるはずです。
もちろん、受信機が一貫して遅い場合は、ストールが繰り返される可能性があります。
送信者と受信者が異なるかのように言いましたが、実際には、両方のピアがすべての ACK パケットでウィンドウの更新を交換しており、どちらの側でもウィンドウがいっぱいになる可能性があります。
全体的なメッセージは、ウィンドウ更新パケットを直接送信する必要はないということです。なりすましは実際には悪い考えです。
あなたが見ている例外に関して...ウィンドウ更新パケットによって引き起こされたり妨げられたりする可能性は低いです。ただし、クライアントの読み取り速度が十分でない場合は、データが失われている可能性があります。サーバーでは、Socket.write() 呼び出しからの戻り値を確認する必要があります。書き込もうとしているバイト数よりも少ない可能性があります。これは、送信側の送信バッファがいっぱいになった場合に発生します。これは、TCP ストール中に発生する可能性があります。バイトを失っている可能性があります。
たとえば、write の各呼び出しで 8192 バイトを書き込もうとしているが、呼び出しの 1 つが 5691 を返した場合、次の呼び出しで残りの 2501 バイトを送信する必要があります。そうしないと、クライアントはその 8K ブロックの残りを認識できず、クライアント側のファイルはサーバー側よりも短くなります。