基于tornado实现websocket通信

一、什么是websocket?

    websocket是html定义的一种标准的协议, 旨在解决浏览器与服务器之间的全双工通信,比如微信好友上线通知、新闻热点通知等,都可以通过websocket来实现服务器向客户端发送消息。
  websocket能够解决Http+HTML在应用中的局限性。
在这里插入图片描述

二、基于tornado实现websocket通信

1.WebsocketHandler学习

  WebsocketHandler是tornado.web框架下封装的处理websocket通信的类,继承WebsocketHandler类,能实现对Websocket消息的操作,WebsocketHandler的常用函数有:

1) WebSocketHandler.open()

    在一个新的WebSocket链接建立时,Tornado框架会调用此函数。在本函数中,我们可以和在get()、post()等函数中一样用get_argument()函数获取客户端提交的参数,以及用get_secure_cookie/set_secure_cookie操作Cookie等,如下:

在这里插入图片描述
  self.stream.set_nodelay(True) : 官方解释: set the no-delay flag for this stream, 在一个数据包在发送中,往往会分为很多很小的消息,这就会导致在发送消息是出现200-500ms的延迟,通过设置set_nodelay(True)能够增大TCP连接时增大带宽以达到减小延时的目的,同时我们应该一个websocket连接一建立的时候去调用这个方法。

2) WebSocketHandler.on_message(message)

  建立WebSocket链接后,当收到来自客户端的消息时,Tornado框架会调用本函数。通常,这是服务器端WebSocket编程的核心函数,通过解析收到的消息做出相应的处理。

3) WebSocketHandler.on_close()

  当WebSocket链接被关闭时,Tornado框架会调用本函数。在本函数中,可以通过访问self.close_code和self.close_reason查询关闭的原因。

4)WebSocketHandler.write_message(message, binary=False)

  用于向与本链接相对应的客户端写消息。

5)WebSocketHandler.close(code=None,reason=None)

  主动关闭WebSocket链接。其中的code和reason用于告诉客户端链接被关闭的原因。参数code必须是一个数值,而reason是一个字符串。

2.基于tornado实现服务端给客户端持续推送时间

服务端server.py

import tornado.ioloop
import tornado.web
import tornado.websocket
from tornado import gen

from tornado.options import define, options, parse_command_line

define("port", default=8888, help="run on given port", type=int)

# 定义一个空的字典
clients = dict()


class IndexHandler(tornado.web.RequestHandler):

    # 异步访问
    @tornado.web.asynchronous
    def get(self):
        print("访问系统首页...")
        self.render("index.html")


class MyWebSocketHandler(tornado.websocket.WebSocketHandler):

    # 有新的连接时open()函数将会被调用,将客户端的连接统一放到clients
    def open(self, *args, **kwargs):
        self.id = self.get_argument("id")
        self.stream.set_nodelay(True)
        clients[self.id] = {"id": self.id, "object": self}
        print(clients)
        print("建立连接...")

    # 客户收到消息将被调用
    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


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("write to client %s:%s" % (key, msg))
        time.sleep(1)


app = tornado.web.Application([
    (r"/", IndexHandler),
    (r"/websocket", MyWebSocketHandler)
])

if __name__ == "__main__":
    threading.Thread(target=send_time).start()
    parse_command_line()
    app.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

客户端index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>系统首页</title>


</head>
<body>
欢迎您!<br>
<a href="javascript:WebSocketTest()">启动websocket</a>
<div id="messages"></div>
</body>


<script type="text/javascript">

    var message_editors=document.getElementById("messages")
    function WebSocketTest(){

      if ("WebSocket" in window){
             message_editors.innerHTML="websocket is supported by windows"
             var ws=new WebSocket("ws://localhost:8888/websocket?id=12345")
             console.log(ws)
              alert("启动websocket!")
             ws.open=function(){
                 ws.send("message to send");
             }

             ws.onmessage=function(evt){
                var recevied_msg=evt.data
                message_editors.innerHTML=message_editors.innerHTML+"<br/>message is reveived:"+recevied_msg
             }

             ws.onclose=function(){
                message_editors.innerHTML=message_editors.innerHTML+"<br/>connection is closed..."
             }
      }else{
          message_editors.innerHTML="websocket not supported by your brower!"
          alert("不支持websockt!")
      }
    }

</script>
</html>

测试以及结果

访问Localhost:8888, 点击启动websocket,观察控制台和浏览器页面信息
1)控制台打印信息:
在这里插入图片描述

2)点击启动websocket, 查看浏览器接收消息:
在这里插入图片描述

Tornado是一个Python的Web框架,提供高性能的非阻塞网络IO,支持异步编程,能够很好地处理高并发的网络请求。而WebSocket是一种基于TCP协议的网络通信协议,与HTTP协议不同,WebSocket可以在客户端和服务器之间建立持久性的连接,实现双向实时通信。 在Tornado中,我们可以使用全局变量来共享变量,也可以使用协程(Coroutine)来实现异步的变量共享。在WebSocket中,我们可以使用WebSocketHandler类来实现客户端和服务器之间的通信,并在类中定义成员变量来共享变量。由于WebSocket是一种长连接,所以在客户端和服务器之间保持连接期间,这些成员变量会一直存在并且可被访问。 以下是一个简单的示例代码,展示了如何在TornadoWebSocket中共享变量: ``` import tornado.ioloop import tornado.web import tornado.websocket # 全局变量 global_var = 0 # 定义WebSocketHandler类 class MyWebSocketHandler(tornado.websocket.WebSocketHandler): # 成员变量 member_var = 0 def open(self): print("WebSocket opened") # 共享全局变量 global global_var global_var += 1 # 修改成员变量 self.member_var += 1 def on_message(self, message): print("Received message: {}".format(message)) def on_close(self): print("WebSocket closed") # 定义HTTP请求处理类 class MainHandler(tornado.web.RequestHandler): def get(self): # 访问全局变量 global global_var self.write("Global variable: {}\n".format(global_var)) # 访问成员变量 ws = MyWebSocketHandler() self.write("Member variable: {}\n".format(ws.member_var)) # 定义应用程序对象 application = tornado.web.Application([ (r"/", MainHandler), (r"/ws", MyWebSocketHandler), ]) if __name__ == "__main__": application.listen(8888) tornado.ioloop.IOLoop.current().start() ``` 相关问题: 1. 什么是Tornado? 2. 什么是WebSocket? 3. Tornado如何实现非阻塞网络IO? 4. WebSocket和HTTP有什么区别? 5. 如何在Python中使用协程?
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乌托邦钢铁侠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值