为什么Python http服务器导致android VolleyError

时间:2014-06-27 16:11:18

标签: java android python http android-volley

我遵循简单的Python 3.4脚本:

LISTEN_PORT = 7000

class MyHandler(http.server.SimpleHTTPRequestHandler):

    def do_GET(self):
        print("DO GET")
        self.send_response(200, "OK")



def run():

    handler = MyHandler
    print("Server Started")
    httpd = socketserver.TCPServer(("0.0.0.0", LISTEN_PORT), handler)

    try:
        print("serving at port", LISTEN_PORT)
        httpd.serve_forever()
    except KeyboardInterrupt:
        httpd.socket.close()


run()

当我从android调用时:

final StringRequest request = new StringRequest(Request.Method.GET, context.getString(R.string.domain)+"/", new Response.Listener<String>() {
        @Override
        public void onResponse(String s) {

        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {

            Log.e(TAG, "Can not send token" + volleyError);
            Toast.makeText(context, "Can not send", Toast.LENGTH_LONG).show();
        }
    });

    Volley.newRequestQueue(context).add(request);

机器人: 我看到Toast&#34;无法发送&#34;在logcat控制台上我有以下信息:

06-27 18:05:16.332  28946-28946/com.example.code E/NETWORK_CONNECTOR﹕ Can not send token Code:com.android.volley.NoConnectionError: java.io.EOFException

的Python:

192.168.12.246 - - [27/Jun/2014 18:15:55] "GET / HTTP/1.1" 200 -
DO GET

Python脚本有什么问题?

3 个答案:

答案 0 :(得分:1)

python脚本有什么问题?

它会以某种方式与python3.0-3.2一起使用但不适用于python3.3 +

来自send_response documentation

  

版本3.3中更改:标题存储到内部缓冲区,并且需要显式调用end_headers()。

在当前设置中,http答案的标题部分根本不会被发送。

所以在python3.3 +中正确的方法是

def do_GET(self):

    print("DO GET")
    self.send_response(200, "OK")
    self.end_headers()

    self.wfile.write(b"Response body\n") #optional

但是你的脚本中有几件可以改进的东西

  • 使用http.server.BaseHTTPRequestHandler而不是http.server.SimpleHTTPRequestHandler,因为SimpleHTTPRequestHandler为BaseHTTPRequestHandler添加了一些魔法来处理GET和 HEAD 请求。当你重写do_GET时,你替换了SimpleHTTPRequestHandler的行为,但是因为你没有为do_HEAD做,你的服务器会回答HEAD请求,因为它是SimpleHTTPRequestHandler,这不是一个好主意
  • httpd.server_close()而不是httpd.socket.close(),即使它没有太多改变,因为它在当前的python中基本上是一个noop

在脚本顶部添加导入并发送完整的工作脚本

import http.server
LISTEN_PORT = 7000

class MyHandler(http.server.BaseHTTPRequestHandler):

    def do_GET(self):

        print("DO GET")
        self.send_response(200, "OK")
        self.end_headers()

        self.wfile.write(b"Response body\n") #optional


def run():

    handler = MyHandler
    print("Server Started")
    httpd = http.server.HTTPServer(("0.0.0.0", LISTEN_PORT), handler)

    try:
        print("serving at port", LISTEN_PORT)
        httpd.serve_forever()
    except KeyboardInterrupt:
        httpd.server_close()


if __name__ == "__main__":
    run()

答案 1 :(得分:0)

由于EOF异常,似乎响应可能不完整。 尝试将do_GET更改为以下内容:

self.send_response(200)
self.end_headers()

答案 2 :(得分:0)

它与Android无关(提示:您可以从简单的Web浏览器检查您的服务器)。 根据协议规范,HTTP服务器必须以行

开始响应
HTTP/<version> <code> <optional message>

然后服务器发送其他标题,空行和可选的二进制正文(在某些情况下)。 事实证明,状态消息的行为类似于标题,尽管它没有在文档中明确公开。因此,您必须在end_headers()之后致电send_response()

只需将其添加到您的代码中即可。

def do_GET(self):
    print("DO GET")
    self.send_response(200, "OK")
    self.end_headers()
    # Send optional body in HTML, XML, JSON, binary data, etc.
    self.wfile.write(bytes('<html><body>Hello!</body></html>', 'utf-8'))

如果您添加了正文,则可以在浏览器http://localhost:7000中输入并查看问候消息。之后,从Andriod应用程序重新检查服务器。

同时将http.server.SimpleHTTPRequestHandler更改为http.server.BaseHTTPRequestHandler,后者就足够了。