2013-08-07 16 views
6

竜巻IOStreamのタイムアウトを設定するには?竜巻IOStreamのタイムアウトを設定するには?

私はでのIOStreamを構築しようとしました:

sock = socket.socket() 
sock.settimeout(5) 
self.stream = tornado.iostream.IOStream(sock) 

しかし、私はstream.read_bytes()を呼び出すとき、それはまだ永遠に待たせ。

答えて

1

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) 

幸運!

関連する問題