【发布时间】:2012-10-16 02:00:34
【问题描述】:
在写入套接字时我有一个非常奇怪的行为。 在我的移动客户端中,我使用了一个初始化如下的套接字:
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由同行重置)”。之后程序关闭套接字,重新初始化它:
// close
is.close();
os.close();
socket.close();
// reinitialize
initSocket();
并尝试如上所述再次写入数据。然后我看到了问题:连接建立,写入成功,但是没有数据到达服务器!
可能与 ECONNRESET 有关系,可能没有,但我想提一下,因为它可能很重要。
如果有任何想法和提示,我将不胜感激。
附:也许它起到了一些作用:客户端代码在移动的 Android 移动设备上运行(它在汽车中)。互联网连接是通过 GPRS 建立的。
UPD:我可以重现它!至少部分(客户端发送 A、B、C、D、E 而服务器只接收 A)。每次都会发生,如果:
连接建立,客户端读写->OK
连接丢失(我关闭了我的 WLAN 路由器 :)),我变成了 IOException,我关闭了流和套接字 -> 好的
我打开我的路由器,连接回来了,我再次初始化套接字,程序执行 write() 无异常,但是......没有数据到达服务器。
顺便说一句,由于连接再次返回,available() 总是返回 0。
【问题讨论】:
-
拥有一个可以尝试与设备同步的服务器可能会有所帮助。如果它第一次错过了数据,它总是可以重试 - 取决于您轮询数据的频率。
-
@max,当然,你是对的。但是服务器是封闭软件,我无法更改协议。
-
你不能用
ByteArrayOutputStream吗?某事like this -
@Asok 是的,我可以。但为什么?为什么要解决这个问题?
-
@Asok 没问题,你不应该道歉 :) 我感谢每一个建议!
标签: java android network-programming java-io