为什么即使在相关的HTTPResponse关闭后也可以使用HttpConnection

时间:2016-01-28 09:01:24

标签: python

请参阅以下用Python 2.7编写的代码

import httplib

HOST, PORT, PATH = '127.0.0.1', 8888, '/'  # mask


def test():
    conn = httplib.HTTPConnection(HOST, PORT)
    conn.request('GET', PATH, None, headers={})
    rsp = conn.getresponse()
    print rsp.status
    rsp.close()  # close response

    conn.request('GET', PATH, None, headers={})
    rsp2 = conn.getresponse()
    print rsp2.status


test()

服务器将始终返回 403 进行测试。但是test()的结果是

  

403 200

看起来很有线!这里有两个问题

  1. 为什么即使在关闭后仍然可以使用连接 HTTPResponse ,底层套接字是否已关闭? 看起来底座插座没有关机。

  2. 为什么 200 会被退回?

  3. 以下是使用Tornado的服务器代码

    import tornado.ioloop
    import tornado.web
    
    
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
            self.set_status(403)
            self.write('<html>\r\nhello world\r\n</html>')
    
    def make_app():
        return tornado.web.Application([
            (r"/", MainHandler),
        ])
    
    
    if __name__ == "__main__":
        app = make_app()
        app.listen(8888)
        tornado.ioloop.IOLoop.current().start()
    

1 个答案:

答案 0 :(得分:1)

因为你关闭文件位于套接字顶部而不是套接字。

引用socket.makefile

的文档
  

返回与套接字关联的文件对象。 (文件对象是   在文件对象中描述。)文件对象不关闭套接字   显式何时调用其close()方法,但只删除它   引用套接字对象,以便在关闭套接字时使用   它不会被其他任何地方引用。

链接:https://docs.python.org/2/library/socket.html

close中的HTTPResponse关闭self.fp,这是self.fp = sock.makefile(... __init__ HTTPResponse方法中httplib的结果conn }}

套接字仍在200对象中引用,因此不会自动关闭。

(有些人会说:使用源Luke

至于为什么服务器返回HTTPResponse.close ...你需要让全世界知道你正在测试什么以及通信(HTTP内容)的样子。

在评论后编辑:

conn不会消耗任何东西。它只是删除对套接字的引用,但您仍然在200中有引用。

数据保留在套接字缓冲区中,直到套接字真正关闭。

您收到getresponse,因为第二个getresponse尝试解析缓冲区中的数据。并且因为没有找到正确的 HTTP状态行(它被第一个HTTPResponse使用),结果是200认为它是旧的HTTP 0.9服务器并设置默认答案代码为HTTPResponse._read_status

代码位于<em>