codecamp

Tornado 基于基本IOStream的 TCP 服务器

class tornado.tcpserver.TCPServer(ssl_options: Union[Dict[str, Any], ssl.SSLContext, None] = None, max_buffer_size: Optional[int] = None, read_chunk_size: Optional[int] = None)

一个非阻塞的单线程 TCP 服务器。

要使用 ​TCPServer​,请定义一个覆盖 ​handle_stream方法的子类。 例如,一个简单的echo服务器可以这样定义:

from tornado.tcpserver import TCPServer
from tornado.iostream import StreamClosedError
from tornado import gen

class EchoServer(TCPServer):
    async def handle_stream(self, stream, address):
        while True:
            try:
                data = await stream.read_until(b"\n")
                await stream.write(data)
            except StreamClosedError:
                break

要使此服务器为 SSL 流量提供服务,请发送带有 ​ssl.SSLContext​ 对象的 ​ssl_options​ 关键字参数。 为了与旧版本的 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初始化遵循以下三种模式之一:

1、​listen​:简单的单进程:

server = TCPServer()
server.listen(8888)
IOLoop.current().start()

2、​bind​/​start​:简单的多进程:

server = TCPServer()
server.bind(8888)
server.start(0)  # Forks multiple sub-processes
IOLoop.current().start()

使用此接口时,不得将 ​IOLoop传递给 ​TCPServer构造函数。 ​start将始终在默认单例 ​IOLoop上启动服务器。

3、​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​ 一起使用,以便在分叉发生时为您提供更大的灵活性。 如果您想以非 ​bind_sockets的方式创建侦听套接字,​add_sockets也可用于单进程服务器。

3.1 版中的新功能:​max_buffer_size ​参数。

在 5.0 版更改: ​io_loop​ 参数已被删除。

listen(port: int, address: str = '') → None

开始接受给定端口上的连接。

可以多次调用此方法来侦听多个端口。 监听立即生效; 之后无需调用 ​TCPServer.start​。 但是,必须启动 ​IOLoop

add_sockets(sockets: Iterable[socket.socket]) → None。

使此服务器开始接受给定套接字上的连接。

sockets参数是一个套接字对象列表,例如由 ​bind_sockets返回的那些。 ​add_sockets通常与该方法和 ​tornado.process.fork_processes 结合使用,以更好地控制多进程服务器的初始化。

add_socket(socket: socket.socket) → None

add_sockets的单一版本。 采用单个套接字对象。

bind(port: int, address: Optional[str] = None, family: socket.AddressFamily = <AddressFamily.AF_UNSPEC: 0>, backlog: int = 128, reuse_port: bool = False) → None

将此服务器绑定到给定地址上的给定端口。

要启动服务器,请调用 ​start​。 如果您想在单个进程中运行此服务器,您可以调用 ​listen作为绑定和启动调用序列的快捷方式。

地址可以是 IP 地址或主机名。 如果是主机名,服务器将侦听与该名称关联的所有 IP 地址。 Address 可以是空字符串或 None 以侦听所有可用接口。 Family 可以设置为 ​socket.AF_INET​ 或 ​socket.AF_INET6​ 以限制 IPv4 或 IPv6 地址,否则将使用两者(如果可用)。

backlog参数与 ​socket.listen​ 的含义相同。 重用端口参数与 ​bind_sockets​ 具有相同的含义。

在开始侦听多个端口或接口之前,可能会多次调用此方法。

在 4.4 版更改: 添加了 ​reuse_port参数。

start(num_processes: Optional[int] = 1, max_restarts: Optional[int] = None) → None

在 ​IOLoop中启动此服务器。

默认情况下,我们在这个进程中运行服务器,并且不会派生任何额外的子进程。

如果 ​num_processes为 ​None或 <= 0,我们会检测这台机器上可用的内核数量并派生该数量的子进程。 如果给定 ​num_processes并且 > 1,我们将分叉特定数量的子进程。

由于我们使用进程而不是线程,因此任何服务器代码之间都没有共享内存。

请注意,多个进程与 ​autoreload模块(或 ​tornado.web.Application​ 的 ​autoreload=True​ 选项,当 ​debug=True​ 时默认为 ​True​)不兼容。 当使用多个进程时,在调用 ​TCPServer.start(n)之前不能创建或引用任何 ​IOLoop​。

Windows 不支持除 1 以外的 ​num_processes值。

max_restarts参数被传递给 ​fork_processes​。

在 6.0 版更改: 添加了 ​max_restarts参数。

stop() → None

停止侦听新连接。

在服务器停止后,当前正在进行的请求可能仍会继续。

handle_stream(stream: tornado.iostream.IOStream, address: tuple) → Optional[Awaitable[None]]

重写以处理来自传入连接的新 ​IOStream​。

这个方法可能是协程; 如果是这样,它将记录异步引发的任何异常。 此协程不会阻止接受传入连接。

如果此 ​TCPServer配置为 ​SSL​,则可能会在 ​SSL握手完成之前调用 ​handle_stream​。 如果您需要验证客户端的证书或使用 ​NPN​/​ALPN​,请使用 ​SSLIOStream.wait_for_handshake​。

在 4.2 版更改: 添加了将此方法作为协程的选项。


Tornado IOStream连接工厂
Tornado 基于生成器的协程
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }