如何为Tornado IOStream设置超时时间?

6
如何为Tornado的IOStream设置超时时间?
我尝试通过以下方式构建IOStream:
sock = socket.socket()
sock.settimeout(5)
self.stream = tornado.iostream.IOStream(sock)

但是当我调用stream.read_bytes()时,它仍然会永远等待。

1个回答

3

由于 socket.settimeout() 是为阻塞IO设计的,而 Tornado 提供了非阻塞IO,因此您无法使用它。

Tornado 非常注重Web和HTTP IO,并且不允许进行低级网络编程,否则会非常困难(IOStream 的源代码是令人恐惧的)。

在套接字上设置超时时间的最佳方法是使用 select.select(), select.poll() 等方法,但将这种方法与 Tornado 集成起来会比较麻烦。

我成功地使用了 gen.with_timeout 和一个用于清除流状态的脏技巧来执行带有超时的读取。

from tornado import gen
from tornado.ioloop import IOLoop
from tornado.tcpclient import TCPClient

timeout = 5
io_loop = IOLoop.current()
factory = TCPClient(io_loop=io_loop)

@gen.coroutine
def run():
    stream = yield factory.connect('127.0.0.1', 1234)
    try:
        future = stream.read_bytes(128)
        data = yield gen.with_timeout(
            timeout=io_loop.time() + timeout,
            future=future,
            io_loop=io_loop,
        )
    except gen.TimeoutError:
        # A dirty hack to cancel reading and to clear state of the stream, so
        # stream will be available for reading in future
        io_loop.remove_handler(stream.socket)
        state = (stream._state & ~io_loop.READ)
        stream._state = None
        stream._read_callback = None
        stream._read_future = None
        stream._add_io_state(state)

祝你好运!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接