0

自从从冰淇淋三明治升级到果冻豆后,我在客户端(Galaxy Nexus)和自定义服务器之间似乎存在时间问题。这是一般流程:

  1. 客户端打开套接字,发送 HTTP 到服务器
  2. 服务器接受,启动新线程,以 HTTP 标头和 200 OK 响应。
  3. 服务器将(二进制)文件写入套接字。
  4. 客户端从套接字读取数据并保存到文件中。
  5. 服务器线程写入所有数据后,关闭套接字,并终止

在 Jelly Bean 更新之前的几个月里,这一直运作良好。自更新以来,二进制传输的成功率约为 70%。当 'serverSocket.getInputStream().read' 返回 -1 表示已到达流的末尾时,剩余的 30% 失败。未读取任何数据,未引发错误异常,logcat 中没有任何内容。

当我在步骤 5 中更改服务器行为时,可能会出现计时问题。线程在写入后关闭套接字并观察到问题。如果我删除套接字关闭,在写入后终止线程,并让操作系统最终关闭套接字,那么它似乎一直在工作。

我使用 tcpdump 和 WireShark 来查看成功和失败情况下的数据包。在失败的情况下,套接字会在几毫秒内关闭,而在成功的情况下,套接字会在四分之一秒或更多秒内关闭。这样做的结果是,我们在套接字关闭中造成的任何延迟都会提高我们成功的机会。

如果有人对我们可能会导致此问题的措施有任何建议,或者对如何缩小问题范围有任何建议,请随时回复。如果需要,我可以添加代码示例。

4

1 回答 1

-1

看起来当服务器请求关闭连接时,套接字立即关闭。也许默认的 ocket 逗留时间在版本之间发生了变化???

尝试使用以下方法设置套接字逗留时间:

socket.setSoLinger(boolean on, int timeout);

如果某些数据仍在等待发送,则让服务器在关闭通道之前等待一段时间。

如果这不能解决,您可以将上面的流程更改为:

...

4.Client从socket读取数据并保存到文件中。

5.Client向服务器发送确认。

6.服务器关闭连接。

--EDITED-- 在没有额外的 TCP 数据包传输结束确认的情况下实现上述目标的优雅方法是:

当服务器完成写入套接字调用时:

socket.shutdownOutput();

当客户端 socket.read() 返回 -1 时,客户端调用:

socket.close();

这确保客户端被告知所有数据都已发送,并且发送方将等待套接字关闭协议完成。

于 2012-10-07T01:23:58.587 回答