Python:Tornado 第三章:HTML5 WebSocket概念及應用:第二節:服務端編程

上一篇文章: Python:Tornado 第三章:HTML5 WebSocket概念及應用:第一節:WebSocket概念
下一篇文章: Python:Tornado 第三章:HTML5 WebSocket概念及應用:第三節:客戶端編程

Tornado定義了tornado.websocket.WebSocketHandler類用於處理WebSocket連接的請求,應用開發者應該繼承該類並實現其中的open()、on_message()、on_close()函數。html

  • 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函數。node

  • WebSocketHandler.write_message(message,binary=False)函數:用於向與本連接相對於的客戶端寫入消息。
  • WebSocketHandler.close(code=None,reason=None)函數:主動關閉WebSocket連接。其中的code和reason用於告訴客戶端連接被關閉的緣由。參數code必須是一個數值,而reason是一個字符串。

下面是持續爲客戶端推送時間消息的Tornado WebSocket程序:web

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啓動並運行。
相關文章
相關標籤/搜索