Java(ゲームと元のサーバーソフトウェアはJavaで記述されています)でゲーム用の独自のカスタムサーバーソフトウェアを作成しています。利用可能なプロトコルドキュメントがないため、 Wiresharkでパケットを読み取ります。
クライアントが接続している間、サーバーはレベルファイルをGzip形式で送信します。レベルを送信する約94パケットで、サーバーはArrayIndexOutOfBoundsExceptionでクライアントをクラッシュさせます。元のサーバーからのキャプチャファイルによると、その時点でTCPウィンドウアップデートを送信します。TCPウィンドウアップデートとは何ですか、どのようにすればよいですか? SocketChannelを使用して送信しますか?
TCPウィンドウは、接続上のピア間のフロー制御に使用されます。 ACKパケットごとに、ホストは「ウィンドウサイズ」フィールドを送信します。このフィールドは、ホストがいっぱいになる前に受信できるデータのバイト数を示します。送信者は、その量を超えるデータを送信することは想定されていません。
クライアントが十分な速度でデータを受信していない場合、ウィンドウがいっぱいになる可能性があります。つまり、TCPバッファは、アプリケーションがソケットからの読み取り以外の処理を行っていないときにいっぱいになる可能性があります。その場合、クライアントは「ウィンドウがいっぱい」のACKパケットを送信します。ビットが設定されています。その時点で、サーバーはデータの送信を停止することになっています。ウィンドウがいっぱいのマシンに送信されたパケットは、notで確認されます。(これにより、動作の悪い送信者が再送信されます。動作の良い送信者は、送信データをバッファリングするだけです。送信側のバッファもいっぱいになると、送信アプリは、ソケットにさらにデータを書き込もうとするとブロックします。 )
これはTCPストールです。さまざまな理由で発生する可能性がありますが、最終的には、送信者が受信者が読み取っているよりも速く送信していることを意味します。
受信側のアプリがソケットからの読み取りに戻ると、バッファリングされたデータの一部が排出され、スペースが解放されます。次に、受信者は「ウィンドウ更新」パケットを送信して、送信できるデータ量を送信者に通知します。送信者はバッファリングされたデータの送信を開始し、トラフィックは正常に流れるはずです。
もちろん、レシーバーが常に遅い場合は、ストールが繰り返される可能性があります。
送信者と受信者が異なるかのようにこれを言いましたが、実際には、両方のピアがすべてのACKパケットでウィンドウの更新を交換しており、どちらかの側でウィンドウがいっぱいになることがあります。
全体的なメッセージは、ウィンドウ更新パケットを直接送信する必要がないということです。 1つを偽装することは実際には悪い考えです。
あなたが見ている例外に関して...それはウィンドウ更新パケットによって引き起こされたり妨げられたりする可能性は低いです。ただし、クライアントが十分な速度で読み取っていない場合は、データが失われている可能性があります。サーバーでは、Socket.write()呼び出しからの戻り値を確認する必要があります。書き込みをしようとしているバイト数より少ない場合があります。これは、TCPストール中に発生する可能性がある送信者の送信バッファがいっぱいになると発生します。バイトを失う可能性があります。
たとえば、書き込みの呼び出しごとに8192バイトを書き込もうとしているが、呼び出しの1つが5691を返す場合、次の呼び出しで残りの2501バイトを送信する必要があります。そうしないと、クライアントはその8Kブロックの残りの部分を認識できず、ファイルはサーバー側よりもクライアント側で短くなります。
これは、TCP/IPスタックの非常に深いところで発生します。アプリケーション(サーバーとクライアント)では、TCP windowsのことを心配する必要はありません。エラーは別のものでなければなりません。
A TCP Window Updateは、送信者と受信者の間で利用可能なバッファサイズを通信することと関係があります。ArrayIndexOutOfBoundsExceptionは、これの考えられる原因ではありません。ほとんどの場合、コードは何らかの種類の取得していないデータ(この時点よりかなり前に、参照しているだけです)。コードとスタックトレースを確認しないと、これ以上何も言うことはできません。
TCP WindowUpdate-これは、セグメントが純粋なWindowUpdateセグメントであることを示します。 WindowUpdateは、受信側のアプリケーションがRXバッファーから既に受信したデータを消費したときに発生し、TCPレイヤーがWindowUpdateを反対側に送信して、空き容量が増えたことを示します。バッファ。通常、TCP ZeroWindow状態が発生した後に表示されます。レシーバー上のアプリケーションがTCPバッファーからデータを取得すると、スペースが解放され、受信者は、現在のウィンドウサイズをアドバタイズするTCP WindowUpdateを送信して、TCP ZeroWindow条件が存在しなくなったことを送信者に通知する必要があります。
TCP/IPに関する多くの情報については、このWebサイト http://www.tcpipguide.com/free/index.htm に飛び込むことができます。
これは通常、単なるトリガーであり、問題の原因ではありません。
たとえば、NIOセレクターを使用している場合、ウィンドウの更新によって書き込みチャネルのウェイクアップがトリガーされることがあります。これにより、コード内の誤ったロジックがトリガーされます。
スタックトレースを取得すると、根本原因が表示されます。