请参阅以下用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
看起来很有线!这里有两个问题
为什么即使在关闭后仍然可以使用连接 HTTPResponse ,底层套接字是否已关闭? 看起来底座插座没有关机。
为什么 200 会被退回?
以下是使用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()
答案 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>