TCPServer模块建立、监听、接受socket。每创建一个连接,都将对应的socket加入到ioloop的监听队列中,并且将socket包装成一个IOStream对象,该对象提供了异步读写socket的功能。
处理完成后一个IOStream对象就是一个来自客户端的连接,TCPServer会调用handle_stream()函数处理该对象,这也是本层与上层的接口。
1、创建套接字,绑定IP、端口,开始监听,由tornado.netutil.bind_sockets 函数完成
def bind_sockets(): sock = socket.socket() #创建套接字 sock.setblocking(0) #设置套接字为非阻塞模式 sock.bind(sockaddr) #为套接字绑定IP、port sock.listen() #开始监听
return sock
2、将套接字添加至IOLoop,并设置回掉函数,由tornado.TCPServer.TCPServer.listen 函数完成
class TCPServer(object): def listen(self, port, address=""): sock = bind_sockets(port, address=address) self.add_sockets(sock) def add_sock(self, sock): if self.io_loop is None: self.io_loop = IOLoop.current() #IOLoop是个单例模式的类,通过该方法获取实例 #将sock添加至ioloop的监听列表,并且设置回掉函数为self._handle_connection,当sock中有tcp请求时,ioloop调用该回调函数 add_accept_handler(sock, self._handle_connection, io_loop=self.io_loop)
3、当sockt中有tcp请求时,ioloop调用回调函数TCPServer._handle_connection,在该函数中会accept TCP请求,然后将与客户端连接的scokt包装成一个iostrean(提供各种异步读取sockt的方法),最后调用self.handle_stream函数处理该iostream实例
class TCPServer(object): def _handle_connection(self, sock, address): stream = IOStream(sock) #将与客户端连接的socket包装成iostream future = self.handle_stream(stream, address) #客户端连接后不一定会立刻发来消息,处理过程也可能是异步的,所以处理连接的函数会返回一个future self.io_loop.add_future(future, lambda f: f.result())#将该future添加到ioloop中