• tornado


    WebSocket概念

    传统的HTTP与HTML技术使用客户端主动向服务器发送请求并获得回复的应用场景。但随着即时通信需求的增多,这样的通信不能满足要求。

    websocket与普通的socket通信类似,打破原来的request和response一对一的通信模型,同时打破了服务器被动接收客户端请求的应用场景。

    websocket是基于HTTP的协议。是用http协议规定传递。协议规定了浏览器和服务端创建连接之后,不断开,保持连接。相互之间可以基于连接进行主动的收发消息,即时通信。

    服务端编程

    Tornado定义了WebSocketHandler类用于处理websocket连接的请求,可以继承该类实现其中的open()on_message()on_close()函数。

    • open():在一个新的连接建立时,会调用此函数,可以获取客户端提交的参数,以及可以操作cookie等。
    • on_message():建立连接后,当收到来自客户端的请求时,会调用此函数。可以通过解析接收到的信息做相应的处理。
    • on_close():当连接被关闭时,会调用此函数。再此函数中,可以通过访问self.close_codeself.close_reason查询关闭的原因。

    除了上述3个字段调用的函数外,还提供了2个开发者主动操作websocket的函数。

    • write_message(message,binary=Flase): 用于向与本链接相对于的客户端写消息。
    • close(code=None,reaon=None): 主动关闭连接,其中code和reason用于告诉客户端连接被关闭的原因。code参数必须是一个数值,而reason是一个字符串。
    import tornado.ioloop
    import tornado.web
    import tornado.websocket
    
    from tornado.options import define, options, parse_command_line
    
    define("port", default=8888, help="run on the given port", type=int)
    
    clients = dict()
    
    class IndexHandler(tornado.web.RequestHandler):
        @tornado.web.asynchronous
        def get(self):
            self.render("index.html")
            
    class MyWebSocketHandler(tornado.websocket.WebSocketHandler):
        
        # 有新链接时被调用执行
        def open(self, *args):
            self.id = self.get_argument("id")
            self.stream.set_nodelay(True)
            client[self.id] = {"id": self.id, "object": self}	# 保存session到字典中
            
         # 收到消息时被调用
        def on_message(self, message):
            print("客户端%s发来一条消息: %s"%(self.id, message))
        
        # 关闭链接时被调用
        def on_close(self):
            if self.id in clients:
                del clients(self.id)
                print("客户端%s断开连接"%(self.id))
                
        def check_origin(self, origin):
            return True
    
    app = tornado.web.Application([
        (r'/', IndexHandler),
        (r'/websocket', MyWebSocketHandler)
    ])
    
    import threading
    import time
    import datetime
    
    # 启动单独的线程运行此函数,每隔一秒向所有的客户端推送当前时间
    def send_time():
        while True:
            for key in clients.keys():
                msg = str(datetime.datetime.now())
                clients[key]["object"].write_message(msg)  #主动发消息
                print("发送给客户端%s:%s"%(key, msg))
            time.sleep(1)
     
    if __name__=='__main__':
        
        threading.Thread(target=send_time).start()	# 启动推送时间的线程
        parse_command_line()
        app.listen(options.port)
        tornado.ioloop.IOLoop.instance().start()
    

    客户端编程

    由于websocket时HTML5的标准之一,所有主流浏览器的web客户端编程语言JavaScript可以支持websocket的客户端编程。

    JavaScript初始化websocket对象:

    var socket = new WebSocket(url);
    

    在代码中只需给websocket的构造函数传入URL地址,比如http://xxx.com。可以为该对象的如下事件指定处理函数以响应它们。

    • WebSocket.onopen: WebSocket连接建立时调用。
    • WebSocket.onmessage: 接收到来自服务器的消息时调用。
    • WebSocket.onerror: 通信错误时调用。
    • WebSocket.onclose: 与服务器连接断开时调用。

    还可以主动进行操作:

    • WebSocket.send(data): 向服务器发送消息。
    • WebSocket.close: 主动关闭连接。
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>WebSocket</title>
    </head>
    <body>
        <a href="javascript:WebSocketTest()">Run WebSocket</a>
        
    	<div id="msg" style="height:200px; background:black; color:white;"></div>
    </body>
    <script type="text/javascript">
    	var messageContainer = document.getElementById("msg");
        
        function WebSocketTest(){
            if ("Websocket" in window){
                messageContainer.innerHTML = "Websocket is supported by your Browser!";
                var ws = new WebSocket("ws://localhost:8888/websocket?id=12");
                
                ws.onopen = function(){
                    ws.send("Message to send");
                };
               	ws.onmessage = function(evt){
                    var recv_msg = evt.data;
                    messageContainer.innerHTML = messageContainer.innerHTML + "<br/>Message is received:" + recv_msg;
                };
                ws.onclose = function(){
                	messageContainer.innerHTML = messageContainer.innerHTML + "<br/>Connection is closed...";
                    
                };
            }eles{
                messageContainer.innerHTML = "WebSocket Not supported by your Browser!";
            }
        }
    </script>
    </html>
    

    上述代码解析:

    • Run WebSocket连接用于让用户启动Websocket;另一个id=msg的div标签用于显示服务器端传来的消息。
    • 使用JavaScript语句if ("Websocket" in window){}可以判断当前浏览器是否支持websocket对象。
    • 如果支持websocket对象,则连接服务器ws://localhost:8888/websocket,并且传入参数 id。然后通过websocket的处理函数,进行消息的展示。onopen事件向服务器发送消息。
  • 相关阅读:
    python requests用法总结
    Linux统计某文件夹下文件的个数
    PM2使用及介绍
    如何区分USB 2.0 和USB 3.0插口
    npm突然找不到npm-cli.js的解决方法
    mRemoteNG
    js中几种实用的跨域方法原理详解
    Tornado异步阻塞解决方案
    [阅读笔记]EfficientDet
    iOS 保存视频AVAssetWriter
  • 原文地址:https://www.cnblogs.com/yzm1017/p/13570774.html
Copyright © 2020-2023  润新知