Tornado HTTP 服务器的绑定方法
在httpserver.py文件里,有一个叫做bind
的方法,这个方法的最后部分有这样的代码:
sock.bind(sockaddr)
sock.listen(128)
self._sockets[sock.fileno()] = sock
if self._started:
self.io_loop.add_handler(sock.fileno(), self._handle_events,
ioloop.IOLoop.READ)
这段代码的意思是,当一个套接字(socket)连接上来,并触发了ioloop.IOLoop.READ
事件时,就会调用self._handle_events
,对吧?
但是每个客户端连接都会生成一个新的文件描述符,对吧?
那么,ioloop是怎么通过sock.fileno()
来监控客户端的套接字连接的呢?(httpserver的bind方法只调用了一次)
1 个回答
0
我刚看了一下源代码,似乎是这样工作的:
Tornado 并不自己监控网络连接,而是把这个工作交给操作系统,使用 epoll
(在 Linux 上)或者 select
。调用 self.io_loop.add_handler
只是为了在有新连接时设置一个回调函数。
客户端连接是通过 self._handle_events
来建立的,每当套接字收到新的连接,就会为这个连接创建一个新的 HTTPConnection
。每个 HTTPConnection
使用的通信套接字是通过调用 sock.accept()
创建的新套接字。服务器会继续在之前的套接字上接受连接。
所以总结一下:
- 是的,当在套接字上检测到新连接时,io_loop 会调用
self._handle_events
。 - 不,套接字会被重用来处理新连接。相反,每个客户端都会创建一个新的
HTTPConnection
对象,并为通信分配一个单独的套接字。 - io_loop 不需要主动监控套接字。它把这个任务交给操作系统,使用
epoll
或select
。与客户端的实际通信是通过HTTPConnection
对象来完成的。
我认为关键在于理解,这里的套接字只是用来接受新连接。当通过 sock.accept()
接受连接时,会返回一个新的用于通信的套接字,然后这个套接字会被附加到一个 HTTPConnection
对象上。