9

ソケットへの書き込み中に非常に奇妙な動作をします。私のモバイル クライアントでは、次のように初期化されたソケットを使用しています。

private void initSocket()
{
    socket = new Socket();
    socket.connect(new InetSocketAddress(host, port));

    os = new DataOutputStream(socket.getOutputStream());
    is = new DataInputStream(socket.getInputStream());
}

次に、定期的に (60 秒ごとに) このソケットにデータを読み書きします (ここのコードは少し簡略化されています)。

if(!isSocketInitialized())
{
    initSocket();
}

byte[] msg = getMessage();

os.write(msg);
os.flush();

int bytesAvailable = is.available( );
if(bytesAvailable>0)
{
    byte[] inputBuffer = new byte[bytesAvailable];

    int numRead = is.read(inputBuffer, 0, bytesAvailable);
    processServerReply(inputBuffer, numRead);
}

そして、それは機能します。しかし... ときどき (ごくまれに、1 日に 1 ~ 2 回) サーバーがデータを受信しないことがあります。クライアント ログは次のようになります。

Written A
Written B
Written C
Written D
Written E

等々。しかし、サーバー側では次のようになります。

Received A
Received E

クライアント側ではすべてのデータが例外なく送信されたように見えるにもかかわらず、B、C、D データ レコードは受信されませんでした。

このようなギャップは小さい場合もあり (2 ~ 3 分)、それほど悪くはありませんが、場合によっては非常に大きくなる場合があり (1 ~ 2 時間 = 60 ~ 120 サイクル)、これは私の顧客にとって本当に問題です。

何が間違っているのか本当にわかりません。データはクライアントから送信されたように見えますが、サーバー側には届きません。プロキシでも確認しました。

私はログしか持っておらず、この問題を再現することはできません (しかし、私の顧客には毎日 1 回以上発生します)。 )」。その後、プログラムはソケットを閉じ、再初期化します。

// close
is.close();
os.close();
socket.close();

// reinitialize
initSocket();

そして、上記のようにデータを再度書き込もうとします。次に、問題が表示されます。接続が確立され、書き込みが成功しましたが、サーバーにデータが到着しませんでした!

それはECONNRESETと関係があるかもしれませんが、そうではないかもしれませんが、重要かもしれないのでこれについて言及したいと思います.

アイデアやヒントをいただければ幸いです。

PS おそらく何らかの役割を果たします。クライアント コードは、移動中の Android モバイル デバイス上で実行されます (車内にあります)。インターネット接続は GPRS 経由で確立されます。


UPD:再現できます!少なくとも部分的に (クライアントは A、B、C、D、E を送信し、サーバーは A のみを受信します)。次の場合は毎回発生します。

  1. 接続が確立され、クライアントが読み取りと書き込みを行う -> OK

  2. 接続が失われました (WLAN ルーターの電源を切りました :))、IOException になりました。ストリームとソケットを閉じます -> OK

  3. ルーターの電源を入れ、接続が回復し、ソケットを再度初期化し、プログラムは例外なく write() を実行しますが... データがサーバーに到着しません。

ところで、接続が再び戻ってきたので、 available() は常に0を返します。

4

2 に答える 2

2

テストを取り除きavailable()ます。ピアが返信すると思われる場合は、それを読んでください。そうしないと、返信を読んでいる場合と読んでいない場合があり、同期が取れなくなります。の正しい使い方はほとんどなくavailable()、これはその 1 つではありません。

于 2012-10-25T22:23:46.610 に答える
1

この奇妙な動作の原因は、サーバー側のソケットが閉じられていないことでした。小さなクライアントとサーバーで再現できました。どちらも数行のコードで構成されており、次のことを行います。

  1. サーバーに接続します
  2. デッドスポットをシミュレートします(たとえば、WiFiをオフにします)
  3. クライアント側のソケットを閉じます
  4. サーバー側のソケットを閉じないでください
  5. WiFiをオンにします
  6. クライアントからの新しい接続を確立する
  7. この接続にデータを書き込む

出来上がり!クライアントはエラーなしでデータを書き込みますが、サーバーはそれを受信しません...

ただし、サーバーがソケットも閉じると、サーバーはこのデータを読み取ることができます。したがって、解決策は、サーバー側でタイムアウトした後にソケットを閉じることです。

残念ながら、私の場合、サーバーはプロプライエタリなサードパーティソフトウェアであるため、実行可能ではありません。

于 2012-11-19T18:19:33.787 に答える