ソケットへの書き込み中に非常に奇妙な動作をします。私のモバイル クライアントでは、次のように初期化されたソケットを使用しています。
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 のみを受信します)。次の場合は毎回発生します。
接続が確立され、クライアントが読み取りと書き込みを行う -> OK
接続が失われました (WLAN ルーターの電源を切りました :))、IOException になりました。ストリームとソケットを閉じます -> OK
ルーターの電源を入れ、接続が回復し、ソケットを再度初期化し、プログラムは例外なく write() を実行しますが... データがサーバーに到着しません。
ところで、接続が再び戻ってきたので、 available() は常に0を返します。