摘要:前言俗話說光說不練假把式上一篇文里都只是光看著別人的源碼說貌似有點紙上談兵的意思所以這次寫一個簡單的自己定義協議的既可以熟悉和的用法又可以在去除了復雜的協議后了解的工作原理代碼不多加上空行和也就行不到在上的源碼點這里目標定義一個簡單的協議達
前言
俗話說"光說不練假把式",上一篇文里都只是光看著別人的源碼說,貌似有點紙上談兵的意思.
所以這次寫一個簡單的,自己定義協議的server.
既可以熟悉Future和coroutine的用法,又可以在去除了復雜的http協議后,了解tornado的工作原理.
代碼不多,加上空行和import也就200行不到.
在github上的源碼點這里
1.定義一個簡單的協議,達到遠程調用的效果,并且是個長連接的協議(類似websock)
2.模仿tornado的框架模式開發這個server框架,讓用戶代碼開發方便,并且支持coroutine
3.為了省去客戶端的開發,客戶端使用telnet
協議1.客戶端連接成后,以換行符分割每次通信內容
2.第一次通信內容是需要執行handler名稱,第二次通信的內容是該handler的方法名
3.對于客戶端的主動close,需等待此連接所有的異步操作完成后才關閉連接
最后運行方式如下圖:
因為想讓代碼盡量少,所以委托模式沒有嚴格按照設計模式的規范寫,直接忽略掉了interface的定義.嚴格來說是需要定義interface和判斷傳入參數的類型的(泛華)
這是類的實例關系圖(也不知道是不是這樣畫...)
MyServer和MyApplication的實例常駐.一個連接進來后就會創建圖中其他的實例各一個.
異步說明1.為了達到目標中的第一點,需要一個while循環,讀取了客戶端數據后,執行handler,
立即繼續讀取下一條客戶端數據.直到客戶端關閉操作,引發StreamClosedError才退出循環
2.為了達到目標中的第二點,判斷handler的返回值,如果類型是Future則yield處理,因為本方法有@gen.coroutine,所以yield就代表異步操作是在gen.Runner中執行的.
3.為了達到目標中的第三點,需要記錄每一個異步操作,并且異步操作完成后移除.當客戶端主動關閉連接時,需判斷是否還有future未完成.所以close代碼中給每個future加上done_callback,用以檢查關閉
詳情見代碼 MyServerConnection._server_request_loop
@gen.coroutine def _server_request_loop(self, delegate): try: #get request adepter request_delegate = delegate.on_request(self) while True: try: message_future = self.stream.read_until_regex(b" ?") message = yield message_future message = self._parse_data(message) except (iostream.StreamClosedError, iostream.UnsatisfiableReadError): app_log.error(" close the connect") self.close() return except Exception: gen_log.error("Uncaught exception", exc_info=True) self.close() return ret = request_delegate.on_message(message) #如果是異步執行的方法,保存future,用于確保close時,所有future都已完成 if isinstance(ret, Future): ret.add_done_callback(lambda f:self._serving_futures.remove(f)) self._serving_futures.append(ret) finally: delegate.on_close(self)
def close(self): def mayby_close(f): futures = self._serving_futures+self._pending_writes app_log.error(futures) if not any(futures): self.stream.close() pending_futrues = self._serving_futures+self._pending_writes if any(pending_futrues): map(lambda f:f.add_done_callback(mayby_close),pending_futrues) else: self.stream.close()關于@coroutine
其實用@coroutine的時候只需要記住幾點就行了
* 1.被包裝的函數(方法),返回值是Future,
* 2.被包裝的函數走完最后一行代碼后,返回的Future的callback就會被運行(因為在Runner中引發了StopIteration錯誤,被set_result了)
* 3.被包裝的函數是在gen.Runner中運行的,而Runner是在ioloop(callback那塊)中運行的
代碼非常簡單,因為tornado為我們提供了異步的庫(tornado真強大,協程好厲害!!),并且是單進程的編程,不需要考慮鎖,寫起來就更輕松了.
最后附上程序效果圖
這只是個吃飽撐著的程序,一點實際作用都沒啊(好想被拍死!).吃飽撐著的原因是我還沒下決心去找工作...工作太難找啦(哭~~)!!!!好想被帶走.................
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/37587.html
摘要:的非阻塞單線程的特點在這個模塊中體現。還有一個模塊引入,是用完成的這兩句就顯示了所謂命令行解析模塊的用途了。表示可以接收來自的請求了。以上把一個簡單的剖析。 As he walked by the sea of Galilee, he saw two brothers, Simon, who is called Peter, and Andrew his brother, cas...
摘要:主要是為了實現系統之間的雙向解耦而實現的。問題及優化隊列過長問題使用上述方案的異步非阻塞可能會依賴于的任務隊列長度,若隊列中的任務過多,則可能導致長時間等待,降低效率。 Tornado和Celery介紹 1.Tornado Tornado是一個用python編寫的一個強大的、可擴展的異步HTTP服務器,同時也是一個web開發框架。tornado是一個非阻塞式web服務器,其速度相當快。...
摘要:要使用協議我們不可能自己實現一個,現在比較流行的解決方案就是使用套接字編程,已經幫我們實現了協議的細節,我們可以直接拿來使用不用關心細節。 前幾天寫了 淺談cgi、wsgi、uwsgi 與 uWSGI 等一些 python web 開發中遇到的一些名詞的理解,今天博主就根據 wsgi 標準實現一個 web server,并嘗試用它來跑 Django、tornado 框架的 app。 編...
摘要:譯者說于年月日發布,該版本正式支持的關鍵字,并且用舊版本編譯同樣可以使用這兩個關鍵字,這無疑是一種進步。其次,這是最后一個支持和的版本了,在后續的版本了會移除對它們的兼容。本節最好直接在或者閱讀,以獲得更好的閱讀體驗格式支持。 譯者說 Tornado 4.3于2015年11月6日發布,該版本正式支持Python3.5的async/await關鍵字,并且用舊版本CPython編譯Torn...
閱讀 3543·2023-04-25 19:56
閱讀 1660·2021-11-12 10:36
閱讀 1781·2021-11-08 13:19
閱讀 1544·2019-08-30 14:06
閱讀 3032·2019-08-30 11:01
閱讀 1711·2019-08-29 13:23
閱讀 2731·2019-08-29 11:18
閱讀 3422·2019-08-26 13:35