zoukankan      html  css  js  c++  java
  • WebSocket初探

    一.WebSocket简单介绍

      随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。

      我们知道,传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如 浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据;这种客户端是主动方,服务端是被动方的传统Web模式 对于信息变化不频繁的Web应用来说造成的麻烦较小,而对于涉及实时信息的Web应用却带来了很大的不便,如带有即时通信、实时数据、订阅推送等功能的应 用。在WebSocket规范提出之前,开发人员若要实现这些实时性较强的功能,经常会使用折衷的解决方法:轮询(polling)Comet技术。其实后者本质上也是一种轮询,只不过有所改进。

      轮询是最原始的实现实时Web应用的解决方案。轮询技术要求客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动。明显地,这种方法会导致过多不必要的请求,浪费流量和服务器资源。

      Comet技术又可以分为长轮询流技术长轮询改进了上述的轮询技术,减小了无用的请求。它会为某些数据设定过期时间,当数据过期后才会向服务端发送请求;这种机制适合数据的改动不是特别频繁的情况。流技术通常是指客户端使用一个隐藏的窗口与服务端建立一个HTTP长连接,服务端会不断更新连接状态以保持HTTP长连接存活;这样的话,服务端就可以通过这条长连接主动将数据发送给客户端;流技术在大并发环境下,可能会考验到服务端的性能。

      这两种技术都是基于请求-应答模式,都不算是真正意义上的实时技术;它们的每一次请求、应答,都浪费了一定流量在相同的头部信息上,并且开发复杂度也较大。

      伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能力。WebSocket的工作流程是这 样的:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询和Comet技术小 了很多。

    WebSocket 属性

    以下是 WebSocket 对象的属性。假定我们使用了以上代码创建了 Socket 对象:

    属性描述
    Socket.readyState 只读属性 readyState 表示连接状态,可以是以下值:0 - 表示连接尚未建立。1 - 表示连接已建立,可以进行通信。2 - 表示连接正在进行关闭。3 - 表示连接已经关闭或者连接不能打开。
    Socket.bufferedAmount 只读属性 bufferedAmount 已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。

    WebSocket 事件

    以下是 WebSocket 对象的相关事件。假定我们使用了以上代码创建了 Socket 对象:

    事件事件处理程序描述
    open Socket.onopen 连接建立时触发
    message Socket.onmessage 客户端接收服务端数据时触发
    error Socket.onerror 通信发生错误时触发
    close Socket.onclose 连接关闭时触发
    // 初始化一个 WebSocket 对象
    var ws = new WebSocket("ws://localhost:9998/echo");
    
    // 建立 web socket 连接成功触发事件
    ws.onopen = function () {
      // 使用 send() 方法发送数据
      ws.send("发送数据");
      alert("数据发送中...");
    };
    
    // 接收服务端数据时触发事件
    ws.onmessage = function (evt) {
      var received_msg = evt.data;
      alert("数据已接收...");
    };
    
    // 断开 web socket 连接成功触发事件
    ws.onclose = function () {
      alert("连接已关闭...");
    };

    WebSocket 方法

    以下是 WebSocket 对象的相关方法。假定我们使用了以上代码创建了 Socket 对象:

    方法描述
    Socket.send() 使用连接发送数据
    Socket.close() 关闭连接

    websocket实现多人连接聊天

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .container{
                border: 1px solid black;
                margin: auto 0;
                 600px;
                height: 300px;
                overflow: auto;
            }
        </style>
    </head>
    <body>
    <div  style="700px;margin: 0 auto">
    <h1>1024聊天室</h1>
        <div class="container"></div>
        <div class="button1">
            <input type="text" id="txt">
            <input type="button" value="发送" id="btn">
        </div>
    </div>
    <script src="/static/jquery-3.3.1.js"></script>
    <script>
       $(function () {
           sendMessage();
       });
    
    
       ws=new WebSocket("ws://127.0.0.1:8888/chat");
    
       //建立连接后执行
       ws.onopen=function(){
    
       };
       // 接受服务端发过来的数据
       ws.onmessage=function (event) {
           $(".container").append(event.data)
        };
       //服务端主动关闭
       ws.onclose=function () {
           
       };
       function sendMessage(){
            $("#btn").click(function () {
            ws.send($("#txt").val());
                })
       };
    </script>
    
    </body>
    </html>
    index.html
    <div style="margin:10px;background-color: khaki ">{{client}}:  {{msg}}</div>
    message.html
    from tornado.web import RequestHandler
    
    
    class indexhandler(RequestHandler):
    
        def get(self, *args, **kwargs):
            self.render("index.html")
    index_request.py
    from tornado.websocket import WebSocketHandler
    import uuid
    user=set()
    
    
    class ChatHandler(WebSocketHandler):
    
        #客户端和服务端已经建立连接,会执行
        def open(self, *args, **kwargs):
            print("来人了")
            user.add(self)
    
        # message 拿到客户端发送的数据
        def on_message(self, message):
            #render_string渲染模板,不send
            content=self.render_string("message.html",client=uuid.uuid4(),msg=message)
            for client in user:
                client.write_message(content)
            # message=message+"第十六届两个号多个"
            # 发送数据给客户端
            # self.write_message(message)
    
        def on_close(self):
            #客户端主动关闭连接
            user.remove(self)
    chat_websocket.py
    from controller.index_request import indexhandler
    from controller.chat_websocket import ChatHandler
    import tornado.ioloop
    import tornado.web
    
    setting={
        'template_path':'templates',
        'static_path':'static'
    }
    
    application=tornado.web.Application([
        (r'/index',indexhandler),
        (r'/chat',ChatHandler)
    ],**setting)
    
    
    if __name__=="__main__":
        application.listen(8888)
        tornado.ioloop.IOLoop.instance().start()
    app.py
  • 相关阅读:
    luogu P1833 樱花 看成混合背包
    luogu P1077 摆花 基础记数dp
    luogu P1095 守望者的逃离 经典dp
    Even Subset Sum Problem CodeForces
    Maximum White Subtree CodeForces
    Sleeping Schedule CodeForces
    Bombs CodeForces
    病毒侵袭持续中 HDU
    病毒侵袭 HDU
    Educational Codeforces Round 35 (Rated for Div. 2)
  • 原文地址:https://www.cnblogs.com/lujiacheng-Python/p/10293792.html
Copyright © 2011-2022 走看看