【发布时间】:2011-11-17 05:10:53
【问题描述】:
这几天让我发疯了。这很难解释和理解,但我会尽力而为。如果我在任何地方不清楚,请提出任何问题。这个问题只发生在我发送一个超过 300Kb 的大数据包时,比如图像。发送较小的数据包可以正常工作。
我有一个与基于 Python 的 JSON-RPC 服务器通信的 Android 服务。通过 WiFi 或 3G 进行通信时,一切正常。然而,当通过 EDGE 进行通信时,一切都变得非常糟糕。 Android 应用程序创建一个 HttpClient 和 HttpPost。发出请求,但从未从服务器收到响应。我已经在“执行”请求之前和之后放置了一些日志语句,并且它永远不会超过那个。如果初始尝试不成功,似乎还会再次发出请求。我在每个“catch”块中都有日志语句,但它们都没有被执行,所以似乎 HTTP 请求是在内部以某种方式再次发出的。
我一直在检查我的服务器上的 RPC 代码,这就是我可以从那里得到的信息。建立套接字连接并从套接字读取数据。检查 netstat 显示已建立的连接几秒钟,然后进入 CLOSE_WAIT。一旦发生这种情况,就不会从套接字(显然)读取更多数据,并且服务器处于连续循环中,直到套接字连接终止。在这一点上,我一直在杀死 JSON-RPC 服务并将其关闭。如果我不杀死它,该服务将占用 100% 的 CPU,我已经让它坐了大约 5 分钟,它似乎没有关闭套接字。
这是从 Android 设备进行 RPC 调用的代码:
DefaultHttpClient client = new DefaultHttpClient();
try {
HttpPost post = new HttpPost(url);
post.setHeader("Content-Type", "application/json");
post.setEntity(new ByteArrayEntity(data));
// I tried these lines on the HttpPost but didn't seem
// to make a difference.
HttpProtocolParams.setVersion(client.getParams(), HttpVersion.HTTP_1_1);
HttpProtocolParams.setUseExpectContinue(client.getParams(), false);
// This doesn't seem to do anything at all...
client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
Log.d("MyAppName", "** About to make HTTP request");
String json = client.execute(post, new BasicResponseHandler());
Log.d("MyAppName", "** Returned from HTTP request!");
JSONObject obj = new JSONObject(json);
if (obj.isNull("result")) {
rtnval = obj.getJSONObject("error").getString("message");
} else {
// More code here...
}
} catch (ClientProtocolException cpe) {
Log.e("MyAppName", "EXCEPTION: " + cpe.getMessage());
} catch (IOException ioe) {
Log.e("MyAppName", "EXCEPTION: " + ioe.getMessage());
} catch (JSONException je) {
Log.e("MyAppName", "EXCEPTION: " + je.getMessage());
} finally {
client.getConnectionManager().shutdown();
}
RPC 端的“违规”代码实际上是在(Python2.7)SimpleXMLRPCServer.py 中 while 循环的第 487 行。 “self.rfile.read”行是连续获得 0 个字节的内容,它永远不会减少 size_remaining,因此永远不会离开循环。我不太担心,我真的很想知道为什么连接会被终止,但为了完整起见,我在问题中添加了这一点。
所以我试图弄清楚 HTTP 连接是如何进入 CLOSE_WAIT 的。它似乎来自 Android 设备,但我似乎无法确定。我尝试将 ByteArrayEntity 设置为分块,但这似乎省略了 JSON-RPC 所需的“Content-Length”标头。
如果有人知道我可以做些什么来保持该连接打开更长的时间或防止它被关闭,我将不胜感激。我还想防止 HTTP 请求被重试。感谢您的帮助!
【问题讨论】:
标签: android httpclient rpc