Tornado定義了tornado.websocket.WebSocketHandler類別用於處理WebSocket連結的請求,應用開發者應該繼承該類別並實現其中的open()、on_message()、on_close()函數。
WebSocketHandler.open()函數:當一個新的WebSocket連結建立時,Tornado框架會呼叫此函數。在本函式中,開發者可以和在get()、post()等函式中一樣用get_argument()函式取得客戶端提交的參數,以及用get_secure_cookie/set_secure_cookir等操作Cookie等。
WebSocketHandler.on_message(message)函數:建立WebSocket連結後,當收到來自客戶端的訊息時,Tornado框架會呼叫本函數。通常,這是伺服器端WebSocket程式設計的核心函數,透過解析收到的訊息做出對應的處理。
WebSocketHandler.on_close()函數:當WebSocket連結關閉時,Tornado框架會呼叫本函數。在本函數中,可以透過造訪self.close_code和self.close_reason查詢關閉的原因。
除了這三個Tornado框架自動呼叫的入口函數,WebSocketHandler也提供了兩個開發者主動操作WebSocket函數。
WebSocketHandler.write_message(message,binary=False)函數:用於向與本連結相對於的用戶端寫入訊息。
WebSocketHandler.close(code=None,reason=None)函數:主動關閉WebSocket連結。其中的code和reason用來告訴客戶端連結被關閉的原因。參數code必須是一個數值,而reason是一個字串。
以下是持續為客戶端推送時間訊息的Tornado WebSocket程式:
import tornado.ioloop import tornado.web import tornado.websocket from tornado import gen from tornado.options import define,options,parse_command_line import asyncio clients=dict()#客户端Session字典 class IndexHandler(tornado.web.RequestHandler): @tornado.web.asynchronous @gen.coroutine def get(self): print("123") self.render("index.html") class MyWebSocketHandler(tornado.websocket.WebSocketHandler): def open(self, *args, **kwargs): #有新链接时被调用 self.id=self.get_argument("Id") self.stream.set_nodelay(True) clients[self.id]={"id":self.id,"object":self}#保存Session到clients字典中 def on_message(self, message):#收到消息时被调用 print("Client %s received a message:%s"%(self.id,message)) def on_close(self): #关闭链接时被调用 if self.id in clients: del clients[self.id] print("Client %s is closed"%(self.id)) def check_origin(self, origin): return True app=tornado.web.Application([ (r'/',IndexHandler), (r'/websocket',MyWebSocketHandler), ]) import threading import time class SendThread(threading.Thread): # 启动单独的线程运行此函数,每隔1秒向所有的客户端推送当前时间 def run(self): # tornado 5 中引入asyncio.set_event_loop,不然会报错 asyncio.set_event_loop(asyncio.new_event_loop()) import datetime while True: for key in clients.keys(): msg = str(datetime.datetime.now()) clients[key]["object"].write_message(msg) print("write to client %s:%s" % (key, msg)) time.sleep(1) if __name__ == '__main__': #启动推送时间线程 SendThread().start() parse_command_line() app.listen(8888) #挂起运行 tornado.ioloop.IOLoop.instance().start()
解析上述程式碼如下:
定義了全域變數字典clients,用於保存所有與伺服器建立WebSocket連結的客戶端資訊。字典的鍵是客戶端id,值是一個由id與對應的WebSocketHandler實例構成的元組(Tuple)
IndexHandler是一個普通的頁面處理器,用於向客戶端渲染主頁index.html。本頁面中包含了WebSocket的客戶端程式。
MyWebSocketHandler是本例的核心處理器,繼承自tornado.web.WebSocketHandler。其中的open()函數將所有客戶端連結儲存到clients字典中;on_message()用於顯示客戶端發送的訊息;on_close()用於將已經關閉的WebSocket連結從clients字典中移除。
函數sendTime()運行在單獨的執行緒中,每隔1秒輪詢clients中的所有客戶端並透過MyWebSocketHandler.write_message()函數向客戶端推送時間訊息。
本例的tornado.web.Application實例中只配置了兩個路由,分別指向IndexHandler和MyWebSocketHandler,仍然由Tornado IOLoop啟動並運行。
以上是Python的Tornado之WebSocket服務端程式設計的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!