0

MulticastSocketネットワーク検出を実行するために、Java で を実装するプログラムがあります。問題は、サーバーArrayListが特定のポート (私の場合は 4446) に 5 秒ごとにアクティブな共有のシリアル化されたいくつかのパケットを送信し、クライアントがそれを受信することです。ただし、ArrayListが変更された場合、サーバーは次の送信時にそれを送信しますが、クライアントは受信時にサーバーがかなり前に送信した古いパッケージを受信します。

次に例を示します。

ArrayListは 1 つの要素を持っています。

サーバー -> 送信 -> 5 秒待機 -> パケット #2 の送信 -> 5 秒待機 ->タイム フレーム中に変更ArrayList-> パケット #3 の送信

クライアント -> アクティブな共有を検索 -> パケット #1 を受信 -> 1 つの要素! わかった!... (無期限に待機できます - この時点までに #2 と #3 がサーバーから送信されています)

クライアント -> アクティブな共有を検索 -> #packet 2 を受信 -> 1 つの要素。番号。

そして、(理想的には) パケット #3 を受信する必要があるため、すべての一貫性が失われます。

クライアントが送信された最新のパケットを常に受信するようにする方法はありますか? ありがとうございました。

4

2 に答える 2

0

マルチキャストは、UDP と同様に、TCP とは異なり、クライアントへの配信の保証も、配信の順序もありません。#3 が得られない場合、クライアントが受信前にデータを破棄している可能性があります。

クライアント/サーバーコードの動作に関する仮定を再確認します。

パケット #3 を失っていますか、それとも #2 の前に配信して #2 を無視したいだけですか? 2 番目のケースの場合は、できるだけ早くすべてのパケットを収集できるようにコードを記述する必要があります。ループ内でパケットを受信した後、タイムアウトを非常に短くして、すぐに receive() を試みるオプションがあります。これは、カーネル ラウンド トリップを意味する so_timeout を調整し、すべてのパケットに対してそれを行うと、コストがかかることを意味する場合があります。

より良い方法は、ソケットから常に読み取りを行うスレッドを用意し、すべてのパケットを別の処理スレッドが読み取る BlockingQueue に入れることです。この方法では、受信時のタイムアウトをあまり気にする必要はありません。また、パケットを消費するだけなので、jvm がソケットからパケットを読み取るのと同じ速さでパケットを取得できます。

于 2012-06-15T02:52:52.793 に答える
0

これは、ネットワーク通信に固有の競合状態です。前のレポートが受信者に転送されている間に、データ ソースの状態が変化します。この時点で、時間を逆にして、既に送信されているデータを更新する必要があります。それができる便利なライブラリが見つからないので、パケットを順番に処理することをお勧めします:)

ここでの本当の答えは、適切な通信プロトコルです。TCP や UDP のようなトランスポートではなく、独自のアプリケーション レベルのプロトコルです。素晴らしい例とインスピレーションを得るために、TCP 状態遷移図を見てください。これは、かなり複雑な問題を扱いやすい状態マシンとして扱うことができることを示しています。クライアント側とサーバー側の両方で状態を定義し、イベントと遷移を定義して、それに応じてコーディングします。

于 2012-06-15T03:01:03.947 に答える