python異步回調(diào)轉(zhuǎn)為同步并實現(xiàn)超時
問題描述
場景:一個服務(wù)端A,一個客戶端B,存在一個socket連接?,F(xiàn)在寫的是客戶端B部分,服務(wù)端不可控。原來是 B先發(fā)送一個包,等待A返回指定內(nèi)容,B再發(fā)送下一個包
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)在想實現(xiàn)一個timeout,并且實現(xiàn)阻塞。B發(fā)送數(shù)據(jù)后阻塞,直到A返回數(shù)據(jù)(或5秒內(nèi)未接受到來自A的返回raise一個錯誤),請教如何實現(xiàn)?
問題解答
回答1:用 Tornado 的話,寫不了幾行代碼吧。
先作個簡單的 Server ,以方便演示:
# -*- coding: utf-8 -*-from tornado.ioloop import IOLoopfrom tornado.tcpserver import TCPServerfrom tornado import genclass 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 5n’)) else:stream.write(’okn’)if __name__ == ’__main__’: Server().listen(8000) IOLoop.current().start()
然后,來實現(xiàn) Client ,基本邏輯是,超時就關(guān)閉連接,然后再重新建立連接:
# -*- coding: utf-8 -*-import functoolsfrom tornado.ioloop import IOLoopfrom tornado.tcpclient import TCPClientfrom tornado import gendef when_error(stream): print ’ERROR’ stream.close() main()@gen.coroutinedef main(): client = TCPClient() stream = yield client.connect(’localhost’, 8000) count = 0 IL = IOLoop.current() while 1:count += 1stream.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: breakIL.remove_timeout(timer)print datayield gen.Task(IL.add_timeout, IOLoop.current().time() + 1)if __name__ == ’__main__’: main() IOLoop.current().start()
相關(guān)文章:
1. MySQL的聯(lián)合查詢[union]有什么實際的用處2. PHP訂單派單系統(tǒng)3. 怎么能做出標(biāo)簽切換頁的效果,(文字內(nèi)容隨動)4. mysql - sql 左連接結(jié)果union右連接結(jié)果,導(dǎo)致重復(fù)性計算怎么解決?5. 網(wǎng)頁爬蟲 - python 爬取網(wǎng)站 并解析非json內(nèi)容6. mysql 遠(yuǎn)程連接出錯10060,我已經(jīng)設(shè)置了任意主機(jī)了。。。7. php多任務(wù)倒計時求助8. 數(shù)組排序,并把排序后的值存入到新數(shù)組中9. 默認(rèn)輸出類型為json,如何輸出html10. mysql時間格式問題
