tornado.tcpserver
— 基于 IOStream
的基础 TCP 服务¶
一个非阻塞, 单线程 TCP 服务.
-
class
tornado.tcpserver.
TCPServer
(io_loop=None, ssl_options=None, max_buffer_size=None, read_chunk_size=None)[源代码]¶ 一个非阻塞, 单线程的 TCP 服务.
想要使用
TCPServer
, 只需要定义一个子类, 复写handle_stream
方法即可. 例如, 一个简单的 echo server 可以做如下定义:from tornado.tcpserver import TCPServer from tornado.iostream import StreamClosedError from tornado import gen class EchoServer(TCPServer): @gen.coroutine def handle_stream(self, stream, address): while True: try: data = yield stream.read_until(b"\n") yield stream.write(data) except StreamClosedError: break
为了使该服务提供 SSL 传输, 通过一个名为``ssl_options`` 的关键字参数 传递进去
ssl.SSLContext
对象即可. 为了兼容旧版本的 Python,ssl_options
也可以是一个字典, 作为`ssl.wrap_socket` 方法的关键字 参数.:ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH) ssl_ctx.load_cert_chain(os.path.join(data_dir, "mydomain.crt"), os.path.join(data_dir, "mydomain.key")) TCPServer(ssl_options=ssl_ctx)
TCPServer
初始化可以是以下三种模式之一:listen
: 简单的单进程模式:server = TCPServer() server.listen(8888) IOLoop.current().start()
-
server = TCPServer() server.bind(8888) server.start(0) # Forks multiple sub-processes IOLoop.current().start()
当使用这个接口,
IOLoop
一定 不能 被传递给TCPServer
构造器.start
总是会在默认单一的IOLoop
上启动服务. add_sockets
: 高级多进程模式:sockets = bind_sockets(8888) tornado.process.fork_processes(0) server = TCPServer() server.add_sockets(sockets) IOLoop.current().start()
add_sockets
接口更加复杂, 但是它可以和tornado.process.fork_processes
一起被使用, 当 fork 发生的时候给你更多灵活性.add_sockets
也可以被用于 单进程服务中, 如果你想要使用bind_sockets
以外的方式 创建你监听的 socket.
3.1 新版功能:
max_buffer_size
参数.-
listen
(port, address='')[源代码]¶ 开始在给定的端口接收连接.
这个方法可能不只被调用一次, 可能会在多个端口上被调用多次.
listen
方法将立即生效, 所以它没必要在TCPServer.start
之后调用. 然而, 必须要启动IOLoop
才可以.
-
add_sockets
(sockets)[源代码]¶ 使服务开始接收给定端口的连接.
sockets
参数是一个 socket 对象的列表, 例如那些被bind_sockets
所返回的对象.add_sockets
通常和tornado.process.fork_processes
相结合使用, 以便于在一个多进程服务初始化时提供更多控制.
-
add_socket
(socket)[源代码]¶ 单数版本的
add_sockets
. 接受一个单一的 socket 对象.
-
bind
(port, address=None, family=<AddressFamily.AF_UNSPEC: 0>, backlog=128)[源代码]¶ 绑定该服务到指定的地址的指定端口上.
要启动该服务, 调用
start
. 如果你想要在一个单进程上运行该服务, 你可以调用listen
作为顺序调用bind
和start
的一个快捷方式.address 参数可以是 IP 地址或者主机名. 如果它是主机名, 该服务将监听在和该名称有关的所有 IP 地址上. 地址也可以是空字符串或者 None, 服务将监听所有可用的接口. family 可以被设置为
socket.AF_INET
或socket.AF_INET6
用来限定是 IPv4 或 IPv6 地址, 否则如果可用的话, 两者 都将被使用.backlog
参数和socket.listen
是相同含义.这个方法可能在
start
之前被调用多次来监听在多个端口或接口上.
-
start
(num_processes=1)[源代码]¶ 在
IOLoop
中启动该服务.默认情况下, 我们在该进程中运行服务, 并且不会 fork 出任何额外 的子进程.
如果 num_processes 为
None
或 <= 0, 我们检测这台机器上可用的 核心数并 fork 相同数量的子进程. 如果给定了 num_processes 并且 > 1, 我们 fork 指定数量的子进程.因为我们使用进程而不是线程, 在任何服务代码之间没有共享内存.
注意多进程模式和 autoreload 模块不兼容(或者是当
debug=True
时tornado.web.Application
的autoreload=True
选项默认为 True). 当使用多进程模式时, 直到TCPServer.start(n)
调用后, 才能创建或者 引用 IOLoops .
-
handle_stream
(stream, address)[源代码]¶ 通过复写这个方法以处理一个来自传入连接的新
IOStream
.这个方法可能是一个协程; 如果是这样, 异步引发的任何异常都将被记录. 接受传入连接不会被该协程阻塞.
如果这个
TCPServer
被配置为 SSL,handle_stream
将在 SSL 握手完成前被调用. 如果你需要验证客户端的证书或使用 NPN/ALPN 请使用SSLIOStream.wait_for_handshake
.在 4.2 版更改: 给这个方法添加了选项, 可以为协程.