tornado websocket

一、长轮询

在扫码登录的页面,服务器是如何知道用户有没有在手机上扫码登录?

通过长轮询的方式,每隔几秒向服务器发送一个请求,服务器判断这个请求中有没有用户扫码。

缺点

1.开销大

2.浪费资源

3.消耗流量

 

二、websocket概念

长轮询消耗太多资源,其中主要原因是客户端和服务端并没有一直连接在一起。

websocket起到的作用,就是让客户端和服务器一直连接在一起。

(一).websocket官话描述

WebSocket协议是基于TCP的一种新的HTML5网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范。

(二).简单理解

客户端和服务器一直连接在一起

 

三、websocket服务端编程

(一).导包

import tornado.websocket

(二).编写一个基类

class BaseWebSocketHandler(tornado.websocket.WebSocketHandler, SessionMixin):
    def get_current_user(self):
        current_user = self.session.get('user')
            if current_user:
                return current_user
            return None
View Code

(三).跳转的Handler

class IndexHandler(BaseHandler):
    @authenticated
    def get(self):
        self.render('08websocket.html')
View Code

(四).websocket的Handler

class MessageWSHandler(BaseWebSocketHandler):
    users = set()

    def open(self):
        MessageWSHandler.users.add(self)

    def on_message(self, message):
        for u in self.users:
            u.write_message(
                '%s-%s-说:%s' % (
                    self.current_user,
                    datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                    message
                ))

    def on_close(self):
        if self in MessageWSHandler.users:
            MessageWSHandler.users.remove(self)
View Code

(五).为WebsocketHandler添加路由

(六).总结

Tornado 定义了 tornado.websocket.WebSocketHandler 这个类,用于处理 WebSocket 链接的请求。

必须继承该类并重写 open()、on_message()、on_close() 这三个函数,Tornado会自动去调用这三个函数。

(1).WebSocketHandler还提供了两个可以主动操作的WebSocket函数

WebSocketHandler.write_message(message)函数:用于向与本链接相对应的客户端写消息。

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

 

四、webscoket客户端编程

WebSocket是HTML5的标准之一,主流浏览器的web客户端编程语言Javascript已经支持WebSocket的客户端编程。

(一).初始化WebSocket对象

var socket = new WebSocket(url);

(二).处理函数

WebSocket.onopen:此事件发生在 WebSocket 链接建立时

WebSocket.onmessage:此事件发生在收到了来自服务器的消息时

WebSocket.onclose:此事件发生在与服务器的链接关闭时

WebSocket.onerror:此事件发生在通信过程中有任何错误时

(三).主动操作函数

WebSocket.send(data):向服务器发送消息

WebSocket.close():主动关闭现有链接

 

五、完整代码

(一).编写Handler

class BaseHandler(tornado.web.RequestHandler):
    def get_current_user(self):
        current_user = self.get_secure_cookie('ID')
        if current_user:
            return current_user
        return None


class BaseWebsocketHandler(tornado.websocket.WebSocketHandler):
    def get_current_user(self):
        current_user = self.get_secure_cookie("ID")
        if current_user:
            return current_user
        return None


class MessageWSHandler(BaseWebsocketHandler):
    users = set()

    def show_message(self, message):
        for u in self.users:
            u.write_message(message)

    def on_open(self):
        print("coming open...")
        self.show_message("{}进入!".format(""))
        MessageWSHandler.users.add(self)  # self是user的实例

    def on_message(self, message):
        print(message)
        for u in self.users:
            self.show_message("{}说:{}".format("", message))
        # self.write_message(message)

    def on_close(self):
        if self in MessageWSHandler.users:
            self.show_message("{}退出!".format(""))
            MessageWSHandler.users.remove(self)


class MainHandler(BaseWebsocketHandler):
    @authenticated
    def get(self):
        self.render("08websocket.html")
View Code

(二).编写模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> WebSocket </title>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.css" rel="stylesheet">
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .box {
            width: 800px;
            margin-left: auto;
            margin-right: auto;
            margin-top: 25px;
        }

        #text {
            width: 685px;
            height: 130px;
            border: 1px solid skyblue;
            border-radius: 10px;
            font-size: 20px;
            text-indent: 1em;
            resize: none;
            outline: none;
        }

        #text::placeholder {
            color: skyblue;
        }

        .btn {
            width: 100px;
            margin: -27px 0 0px 8px;
        }

        #messages {
            padding-left: 10px;
            font-size: 25px;
        }

        #messages li {
            list-style: none;
            color: #000;
            line-height: 30px;
            font-size: 18px;

        }
    </style>
</head>
<body>
<div class="box">
    <div>
        <textarea id="text" placeholder="请输入您的内容"></textarea>
        <a href="javascript:WebSocketSend();" class="btn btn-primary">发送</a>
    </div>
    <ul id="messages">
    </ul>
</div>


<script src="{{ static_url('js/jquery-2.2.0.min.js') }}"></script>


<script type="text/javascript">

    var mes = document.getElementById('messages');
    if ("WebSocket" in window) {
        mes.innerHTML = "发送WebSocket请求成功!";
        // var ws = new WebSocket("ws://127.0.0.1:8000/websocket");
        var ws = new WebSocket("ws://47.98.139.237:8888/websocket");
        ws.onopen = function () {
            alert('连接已打开请聊天')
        };
        ws.onmessage = function (goudan) {

            var received_msg = goudan.data;

            var aLi = $("<li>" + received_msg + "</li>");
            // $(mes).append($(aLi)) //  方法一
            // $(aLi).appendTo(mes); //  方法二
            $(mes).prepend($(aLi))
        };
        ws.onclose = function () {
            mes.innerHTML = mes.innerHTML + "<br>连接已经关闭...";
        };
    } else {
        mes.innerHTML = "发送WebSocket请求失败!"
    }

    function WebSocketSend() {
        ws.send($("#text").val());
        $("#text").val("")
    }
</script>

</body>
</html>
View Code

前端脚本是jquery写法,必须引入jquery.js

 

六、可能会踩到的坑

(一).代理插件引起的websocket失败

(1).问题描述

我在Chrome上安装了一个代理插件,进行***。但使用websocket的时候,会报错。把报错的英文进行翻译:通过代理服务器建立隧道失败。

没有代理插件的浏览器就可以成功发送消息,而且在Chrome上也可以接收到已发送过的数据,但是发送数据就会失败。

(2).原因

代理是把请求通过代理服务器转发给真正的服务器。一般代理只做了http和https,基本不会去做websocket,哪怕是专业的代理。

(3).解决办法

1.退出代理账号,然后重新访问,一切都正常了。

2.换个没有代理插件的浏览器。

3.加白名单,不让插件去代理websocket

(4).补充

尚不清楚蓝灯或者其他***方式会不会遇到类似问题。如果有类似问题,一定要直接评论哈~让别人不要踩坑了

 

转载于:https://www.cnblogs.com/quanquan616/p/9614172.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值