場景:一個(gè)服務(wù)端A,一個(gè)客戶端B,存在一個(gè)socket連線。
現(xiàn)在寫的是客戶端B部分,服務(wù)端不可控。
原來是 B先發(fā)送一個(gè)包,等待A回傳指定內(nèi)容,B再發(fā)送下一個(gè)包
def do():
s.send(...)
yield 1
s.send(...)
yield 2
# 接收到數(shù)據(jù)后的回調(diào)
def callback():
global f
next(f)
f=do()
next(f)
現(xiàn)在想實(shí)作一個(gè)timeout,並且實(shí)作阻塞。 B發(fā)送資料後阻塞,直到A回傳資料(或5秒內(nèi)未接受到來自A的回傳raise一個(gè)錯(cuò)誤),請(qǐng)教如何實(shí)作?
用 Tornado 的話,寫不了幾行程式碼吧。
先作個(gè)簡單的 Server ,以便方便示範(fàn):
# -*- coding: utf-8 -*-
from tornado.ioloop import IOLoop
from tornado.tcpserver import TCPServer
from tornado import gen
class Server(TCPServer):
@gen.coroutine
def handle_stream(self, stream, address):
while 1:
data = yield stream.read_until('\n')
if data.strip() == 'exit':
stream.close()
break
if data.strip() == '5':
IOLoop.current().call_at(IOLoop.current().time() + 5, lambda: stream.write('ok 5\n'))
else:
stream.write('ok\n')
if __name__ == '__main__':
Server().listen(8000)
IOLoop.current().start()
然後,來實(shí)現(xiàn) Client ,基本邏輯是,超時(shí)就關(guān)閉連接,然後再重新建立連接:
# -*- coding: utf-8 -*-
import functools
from tornado.ioloop import IOLoop
from tornado.tcpclient import TCPClient
from tornado import gen
def when_error(stream):
print 'ERROR'
stream.close()
main()
@gen.coroutine
def main():
client = TCPClient()
stream = yield client.connect('localhost', 8000)
count = 0
IL = IOLoop.current()
while 1:
count += 1
stream.write(str(count) + '\n')
print count, '...'
timer = IL.call_at(IL.time() + 4, functools.partial(when_error, stream))
try:
data = yield stream.read_until('\n')
except:
break
IL.remove_timeout(timer)
print data
yield gen.Task(IL.add_timeout, IOLoop.current().time() + 1)
if __name__ == '__main__':
main()
IOLoop.current().start()