websocket的调研使用

websocket

Websocket是HTML5开始提供的一种在单个TCP连接上进行全双工通讯的协议。HTML5规范在2014年10月29日制定完成。
Websocket允许一个建立HTTP连接的双方可以互相推送数据,这意味着不仅仅可以从客户端发送请求数据到服务端,也可以从服务端主动推送数据到客户端,这打破了服务端只能被动处理请求的传统,让一些对数据有实时性要求的app开发变得更加轻松。
以往在没有websocket的时候,为了实现这种实时数据传输,往往会在页面上创建一个定时器用于循环请求服务端数据,这对于页面来说压力过大,特别是定时器在没有正常销毁的时候,多次设定定时器很可能会导致页面卡死。在有了websocket之后,这一切都不是问题,这意味着在web上实现多人在线实时聊天、实时游戏等等成为了可能。

简单了解

websocket必须由浏览器提供支持,所幸现在HTML5已经被绝大部分浏览器支持,在使用的时候,必须还必须前后端配合。浏览器通过javascript向服务器发起websocket连接的请求之后,服务器响应连接,连接成功之后客户端和服务器就可以通过这个连接互相推送数据。
客户端通过send()方法向服务器发送数据,并通过onmessage事件来接收服务器返回的数据。

websocket连接对象包含以下几种事件,可以设置这几种事件的回调函数来实现需求:

事件含义
open连接建立
message客户端接收到服务端数据
error通信发生错误
close连接关闭

客户端javascript代码演示

var ws = new WebSocket("ws://xxxxxxx")
ws.onopen = function() {
    alert("连接建立")
}

ws.onmessage = function(evt) {
    alert("接收数据")
    var msg = evt.data
}

ws.onerror = function() {
    alert("发生错误")
}

ws.onclose = function() {
    alert("连接关闭")
}

对于想要兼容某些不支持websocket的浏览器,你可以检测浏览器的websocket属性并进行后续处理,使用以下代码进行检查:

if ("WebSocket" in window) {
    alert("浏览器支持websocket")
} else {
    alert("浏览器不支持websocket")
}

一个前后端使用websocket的例子(flask && javascript with jQuery)

本例子参考使用Flask-SocketIO完成服务端和客户端的双向通信并在本地通过测试。

python采集cpu实时负载数据,前端使用echart.js库实时显示。
main.py提供数据接口,并且处理根目录路由访问,返回www/index.html文件。

# -*- coding:utf-8 -*-
#!/usr/bin/env python2

from flask import Flask
from flask_socketio import SocketIO
from threading import Thread, Lock
import time
import psutil

app = Flask(__name__)
socketio = SocketIO(app)

thread = None
thread_lock = Lock()

def connecting():
    count = 0
    while True:
        cpus = psutil.cpu_percent(interval=None, percpu=True)
        count += 1
        t = time.strftime('%M:%S', time.localtime())
        socketio.emit('test_data', {
            'data': [t, cpus], 'count': count
        }, namespace='/test')
        socketio.sleep(3)


@socketio.on('connect', namespace="/test")
def test_connect():
    global thread
    with thread_lock:
        if thread is None:
            thread = socketio.start_background_task(target=connecting)

@app.route('/')
def index():
    with open('www/index.html') as f:
        content = f.read()
    return content

if __name__ == "__main__":
    socketio.run(app, debug=True)

index.html放在当前位置www目录下。

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title>websocket测试</title>

        <script type="text/javascript" src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
        <script type="text/javascript" src="//cdn.bootcss.com/socket.io/1.5.1/socket.io.min.js"></script>
        <script src="http://echarts.baidu.com/dist/echarts.min.js"></script>
    </head>

    <body>
        <div id="main"></div>
        <style>
            #main {
                height: 400px;
                width: 80%;
                margin: 10% auto;
            }
        </style>
        <script>
            var myChart = echarts.init(document.getElementById('main'));
            myChart.setOption({
                title: {
                    text: '测试数据'
                },
                tooltip: {},
                legend: {
                    data:['CPU负载']
                },
                xAxis: {},
                yAxis: {},
                series: [{
                    name: 'CPU负载',
                    type: 'line',
                    data: []
                }]
            });

            var time = ["", "", "", "", "", "", "", "", "", ""]
            var cpu = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

            var update_chart = function(res) {
                myChart.hideLoading()

                time.push(res.data[0])
                cpu.push(res.data[1][0])

                if (time.length >= 10) {
                    time.shift()
                    cpu.shift()
                }
                myChart.setOption({
                    xAxis: {
                        type: "category",
                        data: time
                    },
                    yAxis: {
                        name: "CPU负载",
                        type: "value"
                    },
                    series: [{
                        data: cpu,
                        type: 'line'
                    }]
                })
            }

            myChart.showLoading();
            $(document).ready(function() {
                namesapce = "/test"
                var socket = io.connect('ws://localhost:5000/test')

                socket.on('test_data', function(res) {
                    update_chart(res)
                })
            })
        </script>
    </body>
</html>

效果演示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值