基于服务器推送的图片刷新技术演示

最近在做一个类似直播平台的网络应用,想要使前端能不断的从服务器获取视频流。
首先我们要选择一种服务器与浏览器连接方式。目前主要有短链接与全连接两种。
其中短连接又分为传统轮询与长轮询。
轮询(属于短链接):客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。 

优点:后端程序编写比较容易。
缺点:请求中有大半是无用,浪费带宽和服务器资源。
实例:适于小型应用。
长轮询(属于短连接,属于comet技术):客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。 与短轮询相比其实就是增加了超时时间而已。示意图如下
在这里插入图片描述
web客户端代码如下:

//向后台长轮询消息
    function longPolling(){
        $.ajax({
            async : true,//异步
            url : 'longPollingAction!getMessages.action', 
            type : 'post',
            dataType : 'json',
            data :{},
            timeout : 30000,//超时时间设定30秒
            error : function(xhr, textStatus, thrownError) {
                longPolling();//发生异常错误后再次发起请求
            },
            success : function(response) {
                message = response.data.message;
                if(message!="timeout"){
                    broadcast();//收到消息后发布消息
                }
                longPolling();
            }
        });
    }

优点:在无消息的情况下不会频繁的请求,耗费资源小。
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。
实例:WebQQ、Hi网页版、Facebook IM。
长连接:http1.1协议都是默认使用长连接,即浏览器与服务器一直保持连接,即使没有数据要传递。它主要适用于需要频繁发送数据的情景,这样就能减少连接开销。
优点:消息即时到达,不发无用请求;管理起来也相对方便。
缺点:服务器维护一个长连接会增加开销。
实例:Gmail聊天
长连接主要有两大类,一种是服务器单向给客户端推送消息的单工通信,还有两者可以互相发送数据的websocket通信。
单工通信针对字节流的主要技术有基于ajax的字节流实时推送,基于SSE(Server-Event Events)两种方式。在javascript高级程序设计有较为详细的解释。如果是图片需要服务器推送刷新直接指定图片的src为服务器推送网址即可。本次工程的图像刷新就属于单工通信。刷新图片主要是要注意服务器端要指定http协议的报文头部的mineType和Content-Type字段。建议看图解http协议这本书来了解协议细节。
服务器端核心代码如下:

     def gen(camera, start=False):
"""Video streaming generator function."""
        while start:
            frame = camera.get_frame()
            #字符串前面加b表示 后面字符串是bytes 类型。
            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

    @app.route('/cv_camera')
    def cv_camera_feed():
        print("**begin**")
    	camera = Camera_cv()
    #通常一个HTTP响应只能包含一个数据块。但MIME有一种机制可用一个报文(或HTTP响应)表示将多个数据块,
    # 这种机制就是成为“multipart/mixed”的标准MIME类型。
    #这其实是一种基于服务器推送的在浏览器异步刷新的方法
    #“replace”表示每一个新数据块都会代替前一个数据块。也就是说,新数据不是附加到旧数据之后,而是替代它。
    	return Response(
        	gen(camera, True), mimetype='multipart/x-mixed-replace; boundary=frame')

其中camera.get_frame()函数的最后一句是这样。

yield cv2.imencode('.jpg', frame)[1].tobytes()
    """简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,
    Python 解释器会将其视为一个 generator,调用 frames()不会执行frames()函数,而是返回一个 iterable 对象!
    在 for 循环执行时,每次循环都会执行 frames() 函数内部的代码,执行到 yield 语句时,fab 函数就返回一个迭代值"""

Flash Socket:在页面中内嵌入一个使用了Socket类的 Flash 程序JavaScript通过调用此Flash程序提供的Socket接口与服务器端的Socket接口进行通信,JavaScript在收到服务器端传送的信息后控制页面的显示。
优点:实现真正的即时通信,而不是伪即时。
缺点:客户端必须安装Flash插件;非HTTP协议,无法自动穿越防火墙。
实例:网络互动游戏。

参考链接
基于HTTP的长轮询简单实现
https://www.e-learn.cn/content/jquery/1155365
https://www.cnblogs.com/leaven/p/3514650.html

猜你喜欢

转载自blog.csdn.net/qq_25349323/article/details/90261549
今日推荐