• websocket


    WebSocket

    1.长轮询与websocket介绍
    2.websocket编程

     

    1.长轮询与websocket介绍

    长轮询

    长久以来, 创建实现客户端和用户端之间双工通讯的web app都会造成HTTP轮询的滥用:

    ​ 客户端向主机不断发送不同的HTTP呼叫来进行询问。

    这会导致一系列的问题:

    1. 服务器被迫为每个客户端使用许多不同的底层TCP连接:一个用于向客户端发送信息,其它用于接收每个传入消息。

    2. 有线协议有很高的开销,每一个客户端和服务器之间都有HTTP头。

    3. 客户端脚本被迫维护从传出连接到传入连接的映射来追踪回复。

    一个更简单的解决方案是使用单个TCP连接双向通信。 这就是WebSocket协议所提供的功能。 结合WebSocket APIWebSocket协议提供了一个用来替代HTTP轮询实现网页到远程主机的双向通信的方法。

    webscoket介绍

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

    在实现websocket连线过程中,需要通过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为“握手” 。在 WebSocket API,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。在此WebSocket协议中,为我们实现即时服务带来了两大好处:

    1. Header互相沟通的Header是很小的,大概只有 2 Bytes

    2. Server Push服务器的推送,服务器不再被动的接收到浏览器的请求之后才返回数据,而是在有新数据时就主动推送给浏览器。

    websocket的建立过程

    浏览器请求:

    GET /webfin/websocket/ HTTP/1.1     # HTTP请求方式
    Host: localhost   #
    Origin: http://服务器地址    #
    Cookie:_aaa   # cookie
    #以下是建立webscoket链路的核心。  
    Connection: Upgrade
    Upgrade: websocket
    Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==   # 密钥
    Sec-WebSocket-Version: 13            # websocket版本

    服务器回应

    HTTP/1.1 101 Switching Protocols
    ...

    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: K7D JLdLooIwIG/MOpvWFB3y3FE8=

    WebSocket借用http请求进行握手,相比正常的http请求,多了一些内容。其中:
    Upgrade: websocket
    Connection: Upgrade
    表示希望将http协议升级到Websocket协议。

    Sec-WebSocket-Key是浏览器随机生成的base64 encode的值,用来询问服务器是否是支持WebSocket。
    服务器返回:
    Upgrade: websocket
    Connection: Upgrade

    告诉浏览器即将升级的是Websocket协议.
    Sec-WebSocket-Accept是将请求包“Sec-WebSocket-Key”的值,与”258EAFA5-E914-47DA-95CA-C5AB0DC85B11″这个字符串进行拼接,然后对拼接后的字符串进行sha-1运算,再进行base64编码得到的。用来说明自己是WebSocket助理服务器。

    Sec-WebSocket-Version是WebSocket协议版本号。RFC6455要求使用的版本是13,之前草案的版本均应当被弃用。
    更多握手规范详见RFC6455。

     

    2. websocket编程

    websocket的编程分为服务端编程和客户端编程。

    服务端编程

    Tornado定义了 tornado.websocket.WebSocketHandler 类用于处理 WebSocket 链接的请求,应用开发者应该继承该类并实现其中的open()、on_message()、on_close() 函数。

    除了这3个 Tornado 框架自动调用的入口函数,WebSocketHandler 还提供了两个开发者主动操作 WebSocket的函数。

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

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


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

    class MessageWSHandler(BaseWebSocketHandler):
       users = set()

       def open(self):
           # 有新的websocket链接时调用这个函数
           MessageWSHandler.users.add(self)
           print('-------------------open-----------------')

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

       def on_close(self):
           print('-------------------on_close-----------------')
           # 当websocket链接关闭时调用这个函数
           if self in MessageWSHandler.users:
               MessageWSHandler.users.remove(self)
           print(MessageWSHandler.users)

     

    客户端编程

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

    客户短编程围绕着 WebSocket 对象展开,在 Javascript 中可以通过如下代码初始化 WebSocket 对象:


    var socket = new WebSocket(url ):

    在代码中只需给 WebSocket构造函数传入服务器的URL地址,可以为该对象的如下事件指定处理函数以响应它们。

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

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

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

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

    除了这些事件处理函数,还可以通过 WebSocket 对象的两个方法进行主动操作

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

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

    参考代码如下:


    <body>
     
       <div>
           <textarea id="text"></textarea>
           <a href="javascript:WebSocketTest();">发送</a>
       </div>
       <div id="messages" style="height:500px;overflow: auto;"></div>
     
    <script src="{{static_url('js/jquery-2.2.0.min.js')}}"></script>
    <!--<script src="{{static_url('js/bootstrap.min.js')}}"></script>-->
     
       <script type="text/javascript">
           var mes = document.getElementById('messages');
           function WebSocketTest() {
               if("WebSocket" in window){
                   mes.innerHTML = "发送Websocket请求成功!";
                   var ws = new WebSocket("ws://127.0.0.1:8000/websocket");
                   ws.onopen = function () {
                       ws.send($("#text").val()) ;
                  };
                   ws.onmessage = function (evt) {
                       var received_msg = evt.data;
                       mes.innerHTML = mes.innerHTML +
                               "<br>服务器已收到信息:<br>" + received_msg;
                  };
                   ws.onclose = function () {
                     mes.innerHTML = mes.innerHTML + "<br>连接已经关闭...";
                  };
              } else {
                   mes.innerHTML = "发送Websocket请求失败!";
              }
          }
       </script>
    </body>

     

     

     

     

     

     

  • 相关阅读:
    Spring MVC中的(多)文件上传和下载
    SSM整合案例
    事务的四种隔离级别和七种传播行为
    注解方式实现IOC和AOP
    顾问包装通知
    使用ProxyFactoryBean进行AOP
    动态代理(jdk&cglib)的用法
    英语中12个典型的中国式错误
    翻译:你的声音太小了,可以大一些吗
    今天天气怎么样
  • 原文地址:https://www.cnblogs.com/lajiao/p/7856916.html
Copyright © 2020-2023  润新知