在写入套接字期间,我有一个非常奇怪的行为。在我的移动客户端中,我使用了一个初始化如下的套接字:
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 或 2 次)我的服务器不接收数据。我的客户日志如下所示:
Written A
Written B
Written C
Written D
Written E
等等。但在服务器端它看起来像:
Received A
Received E
没有收到 B、C、D 数据记录,尽管事实上在客户端看起来所有数据都毫无例外地发送了!
这样的差距可能很小(2-3 分钟),这不是很糟糕,但有时它们可能非常大(1-2 小时 = 60-120 个周期),这对我的客户来说确实是个问题。
我真的不知道有什么问题。数据似乎是由客户端发送的,但它从未到达服务器端。我也用代理检查过它。
我只有日志,无法重现此问题(但我的客户每天都会发生不止一次),有时我会在日志中看到连接中断并出现异常“sendto failed: ECONNRESET (Connection reset by peer )”。之后程序关闭套接字,重新初始化它:
// 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。