場景:一個服務端A,一個客戶端B,存在一個socket連線。
現在寫的是客戶端B部分,服務端不可控。
原來是 B先發送一個包,等待A回傳指定內容,B再發送下一個包
def do():
s.send(...)
yield 1
s.send(...)
yield 2
# 接收到数据后的回调
def callback():
global f
next(f)
f=do()
next(f)
現在想實作一個timeout,並且實作阻塞。 B發送資料後阻塞,直到A回傳資料(或5秒內未接受到來自A的回傳raise一個錯誤),請教如何實作?
黄舟2017-05-18 11:02:46
用 Tornado 的話,寫不了幾行程式碼吧。
先作個簡單的 Server ,以便方便示範:
# -*- 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()
然後,來實現 Client ,基本邏輯是,超時就關閉連接,然後再重新建立連接:
# -*- 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()