Tornado HTTP 服务器的绑定方法

1 投票
1 回答
1091 浏览
提问于 2025-04-16 23:40

在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 不需要主动监控套接字。它把这个任务交给操作系统,使用 epollselect。与客户端的实际通信是通过 HTTPConnection 对象来完成的。

我认为关键在于理解,这里的套接字只是用来接受新连接。当通过 sock.accept() 接受连接时,会返回一个新的用于通信的套接字,然后这个套接字会被附加到一个 HTTPConnection 对象上。

撰写回答