Android HttpPost 与 Python CGI 服务器不兼容

1 投票
2 回答
2118 浏览
提问于 2025-04-16 13:14

我正在开发一个安卓应用,需要把数据提交到我的Python CGI服务器。通常我用HttpGet从服务器获取数据,这些请求都能正常快速地工作。但是当我尝试用HttpPost推送数据时,程序就会一直卡住,直到我长按模拟器的返回键强制退出程序。CGI服务器似乎开始执行脚本,但在我强制退出安卓应用之前,它一直没有返回。当CGI脚本返回时,它显示CGI script exited OK,但实际上什么都没做。

目前我是在UI线程中执行请求。我知道应该使用AsyncTask来处理这个问题,但我想在找到好的解决方案之前先找到一个临时的解决办法。

我花了三天时间尝试不同的方法,并查看论坛,但都没有找到解决方案。我非常希望能得到一些建议。以下是我安卓代码的相关部分:

private final String serverIP = "10.0.2.2";

HttpClient httpclient = new DefaultHttpClient();
HttpParams params = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 5000);
String URI = "http://"+serverIP+":8000/cgi-bin/test.py?order_submit=0";
HttpPost post = new HttpPost(URI);

List<NameValuePair> kvPairs = new ArrayList<NameValuePair>(2);  
kvPairs.add(new BasicNameValuePair("name", "bob"));
kvPairs.add(new BasicNameValuePair("surname", "the builder"));

try {
    Log.i(TAG, "Trying to set Entity");
    post.setEntity(new UrlEncodedFormEntity(kvPairs, HTTP.UTF_8));

    Log.i(TAG, "Trying to Post");

    HttpResponse response = httpclient.execute(post);

    Log.i(TAG, "execute done");
    httpclient.getConnectionManager().closeExpiredConnections();

} catch (ClientProtocolException e) {
    Log.e(TAG,e.toString());
} catch (UnsupportedEncodingException e) {
    Log.e(TAG,e.toString());
} catch (IOException e) {
    Log.e(TAG,e.toString());
}

在LogCat中输出了以下内容:

INFO/App:(534): Trying to set Entity
INFO/App:(534): Trying to Post
ERROR/App:(534): java.net.SocketTimeoutException: The operation timed out

我的Python CGI服务器脚本如下:

import os, sys, cgi, csv
import cgitb #CGI error backtracer
cgitb.enable()

form = cgi.FieldStorage()

if "order_submit" in form:    
    ofile = open(os.getcwd() + "/Forms/Output/foo.csv", "wb")
    writer = csv.writer(ofile, delimiter=',', quotechar='"',quoting=csv.QUOTE_ALL)
    writer.writerow(["Name", form["name"].value])
    writer.writerow(["Surname", form["surname"].value])
    ofile.close()

在安卓应用请求超时后,foo.csv文件仍然不存在。即使脚本的if部分包含以下内容,并且根本不使用CGI表单,情况也是一样:

if "order_submit" in form:    
    ofile = open(os.getcwd() + "/Forms/Output/foo.csv", "wb")
    writer = csv.writer(ofile, delimiter=',', quotechar='"',quoting=csv.QUOTE_ALL)
    writer.writerow(["Name", "harry"])
    ofile.close()  

httpclient.execute(post);之后,事件的顺序是这样的:
应用程序: httpclient.execute(post);
CGI服务器: POST /cgi-bin/test.py?order_submit=0 HTTP/1.1" 200
CGI服务器: 开始执行第二个Python脚本
等待了几秒钟...
应用程序: java.net.SocketTimeoutException: The operation timed out
Python脚本: 创建了正确的虚拟文件
CGI服务器: CGI script exited OK

2 个回答

0

这个错误的意思是,给定的IP地址无法访问,或者是8000端口被你的网络服务提供商(ISP)屏蔽了,或者是被防火墙挡住了。

0

我把

HttpClient httpclient = new DefaultHttpClient();
HttpParams params = httpclient.getParams();
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 5000);

改成了

HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, timeout);
HttpConnectionParams.setSoTimeout(params, timeout);
HttpClient httpclient = new DefaultHttpClient(params);

现在一切都正常了。我觉得我没有改其他的东西。BasicHttpParams 一定是初始化了一些东西,而 DefaultHttpClient 没有,这很奇怪,因为我之前用的方式在 HttpGet 上也没问题。

撰写回答