19

Java でゲーム用の独自のカスタム サーバー ソフトウェアを作成しています (ゲームと元のサーバー ソフトウェアは Java で作成されています)。利用可能なプロトコル ドキュメントがないため、Wireshark でパケットを読み取る必要があります。

クライアントが接続している間、サーバーはレベル ファイルを Gzip 形式でクライアントに送信します。レベル送信の約 94 パケットで、私のサーバーは ArrayIndexOutOfBoundsException でクライアントをクラッシュさせます。元のサーバーからのキャプチャ ファイルによると、その時点で TCP Window Update を送信します。TCP Window Update とは何ですか? また、SocketChannel を使用して送信するにはどうすればよいですか?

4

7 に答える 7

64

TCP ウィンドウは、接続上のピア間のフロー制御に使用されます。各 ACK パケットで、ホストは「ウィンドウ サイズ」フィールドを送信します。このフィールドは、ホストがいっぱいになる前に受信できるデータのバイト数を示します。送信者は、その量を超えるデータを送信することは想定されていません。

クライアントが十分な速さでデータを受信して​​いない場合、ウィンドウがいっぱいになることがあります。つまり、アプリケーションがソケットからの読み取り以外の処理を行っていない間に、TCP バッファがいっぱいになる可能性があります。その場合、クライアントは「window full」ビットが設定された ACK パケットを送信します。その時点で、サーバーはデータの送信を停止するはずです。フル ウィンドウのマシンに送信されたパケットは、確認応答されません。(これにより、行儀の悪い送信者は再送信します。行儀の良い送信者は、送信データをバッファリングするだけです。送信側のバッファもいっぱいになると、送信側のアプリは、ソケットにさらにデータを書き込もうとするとブロックされます。 !)

これは TCP ストールです。これはさまざまな理由で発生する可能性がありますが、最終的には、受信者が読み取る速度よりも送信者が高速に送信していることを意味します。

受信側のアプリがソケットからの読み取りに戻ると、バッファリングされたデータの一部が排出され、スペースが解放されます。次に、受信者は「ウィンドウ更新」パケットを送信して、送信できるデータ量を送信者に伝えます。送信者はバッファリングされたデータの送信を開始し、トラフィックは正常に流れるはずです。

もちろん、受信機が一貫して遅い場合は、ストールが繰り返される可能性があります。

送信者と受信者が異なるかのように言いましたが、実際には、両方のピアがすべての ACK パケットでウィンドウの更新を交換しており、どちらの側でもウィンドウがいっぱいになる可能性があります。

全体的なメッセージは、ウィンドウ更新パケットを直接送信する必要はないということです。なりすましは実際には悪い考えです。

あなたが見ている例外に関して...ウィンドウ更新パケットによって引き起こされたり妨げられたりする可能性は低いです。ただし、クライアントの読み取り速度が十分でない場合は、データが失われている可能性があります。サーバーでは、Socket.write() 呼び出しからの戻り値を確認する必要があります。書き込もうとしているバイト数よりも少ない可能性があります。これは、送信側の送信バッファがいっぱいになった場合に発生します。これは、TCP ストール中に発生する可能性があります。バイトを失っている可能性があります。

たとえば、write の各呼び出しで 8192 バイトを書き込もうとしているが、呼び出しの 1 つが 5691 を返した場合、次の呼び出しで残りの 2501 バイトを送信する必要があります。そうしないと、クライアントはその 8K ブロックの残りを認識できず、クライアント側のファイルはサーバー側よりも短くなります。

于 2009-09-23T14:56:54.090 に答える
3

TCP WindowUpdate - これは、セグメントが純粋な WindowUpdate セグメントであったことを示します。WindowUpdate は、受信側のアプリケーションが RX バッファーから既に受信したデータを消費したときに発生し、TCP レイヤーが相手側に WindowUpdate を送信して、バッファーに使用可能なスペースが増えたことを示します。通常、TCP ZeroWindow 状態が発生した後に見られます。受信側のアプリケーションが TCP バッファからデータを取得してスペースを解放したら、受信側は、現在のウィンドウ サイズをアドバタイズする TCP WindowUpdate を送信して、TCP ZeroWindow 状態が存在しなくなったことを送信側に通知する必要があります。

https://wiki.wireshark.org/TCP_Analyze_Sequence_Numbers

于 2015-09-07T13:01:54.350 に答える
2

TCP Window Update は、送信者と受信者の間で利用可能なバッファ サイズを通信することに関係しています。ArrayIndexOutOfBoundsException が原因であるとは考えられません。最も可能性が高いのは、コードが取得していない何らかの種類のデータを予期していることです (この時点よりもかなり前に、コードが参照しているだけの可能性があります)。コードとスタック トレースを確認しないと、それ以上のことは言えません。

于 2009-09-23T14:34:35.167 に答える
0

TCP/IP に関する多くの情報については、この Web サイトhttp://www.tcpipguide.com/free/index.htmを参照してください。

于 2009-09-23T14:33:58.583 に答える
0

例外を除いて詳細はわかりますか?

これは、TCP Window Update パケットに関連しているとは考えられません
(複数のインスタンスで正確に繰り返されるのを見たことがありますか?)。

受信したデータで動作する処理コードに関連している可能性が高くなります。

于 2009-09-23T14:39:19.893 に答える
0

これは通常、単なるトリガーであり、問​​題の原因ではありません。

たとえば、NIO セレクターを使用する場合、ウィンドウの更新によって書き込みチャネルのウェイクアップがトリガーされる場合があります。これにより、コード内の誤ったロジックがトリガーされます。

スタックトレースを取得すると、根本原因が示されます。

于 2009-09-23T14:40:58.553 に答える