socket.io-直播视频的消息推送

近日接到需求,需要在“直播后台监控系统”里监控直播间的消息。刚接到需求时一脸懵逼,好在队友给力,Google强大,需求已经上线。现将我完成需求的过程与查阅了解到的知识整理出来,仅供参考,若错误请指教~~

一、什么是WebSocket


WebSocket一种在单个TCP连接上进行全双工通讯的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并被RFC7936所补充规范,WebSocketAPI被W3C定为标准。

WebSocket 是独立的、创建在 TCP 上的协议,和 HTTP 的唯一关联是使用 HTTP 协议的101状态码进行协议切换,使用的 TCP 端口是80,可以用于绕过大多数防火墙的限制。

WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端直接向客户端推送数据而不需要客户端进行请求,在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并允许数据进行双向传送。

1.背景


现在,很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP request的header是非常长的,里面包含的数据可能只是一个很小的值,这样会占用很多的带宽和服务器资源。
而比较新的技术去做轮询的效果是Comet,使用了AJAX。但这种技术虽然可达到双向通信,但依然需要发出请求,而且在Comet中,普遍采用了长链接,这也会大量消耗服务器带宽和资源。
面对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯。

2.握手协议


在实现websocket连线过程中,需要透过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为“握手”(handshaking)。为第13版且浏览器为Chrome的例子:

浏览器请求:

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com
Origin: null
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13

服务器回应:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Origin: null
Sec-WebSocket-Location: ws://example.com/

3.原理


在请求中的“Sec-WebSocket-Key”是随机的,服务器端会用这些数据来构造出一个SHA-1的信息摘要。
把“Sec-WebSocket-Key”加上一个魔幻字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”。使用SHA-1加密,之后进行BASE-64编码,将结果做为“Sec-WebSocket-Accept”头的值,返回给客户端。

4.websocket与Socket.IO


WebSocket提供了一个受欢迎的技术,以替代我们过去几年一直在用的Ajax技术,WebSocket API是下一代客户端-服务器的异步通信方法,它提供了一个方法可以从客户端使用简单的语法有效地推动消息到服务器。HTML5的WebSocket API:它可用于客户端、服务器端。而且有一个优秀的第三方API,名为Socket.IO。

WebSocket API的用法可以参照 认识HTML5的WebSocket
Socket.IO的用法参照官方API socket.io/docs
(ps:官方文档写得很少,但基本的参数配置还是写出来了,如果看了还是懵逼的话,建议直接断点进去把Socket的IO对象的属性方法输出来看)


ps:对websocket的初步认识,其实我更倾向于知乎上(作者:董可人)这段通俗易懂的理解:

你可以把 WebSocket 看成是 HTTP 协议为了支持长连接所打的一个大补丁,它和 HTTP 有一些共性,是为了解决 HTTP 本身无法解决的某些问题而做出的一个改良设计。在以前 HTTP 协议中所谓的 keep-alive connection 是指在一次 TCP 连接中完成多个 HTTP 请求,但是对每个请求仍然要单独发 header;所谓的 polling 是指从客户端(一般就是浏览器)不断主动的向服务器发 HTTP 请求查询是否有新数据。这两种模式有一个共同的缺点,就是除了真正的数据部分外,服务器和客户端还要大量交换 HTTP header,信息交换效率很低。它们建立的“长连接”都是伪.长连接,只不过好处是不需要对现有的 HTTP server 和浏览器架构做修改就能实现。
WebSocket 解决的第一个问题是,通过第一个 HTTP request 建立了 TCP 连接之后,之后的交换数据都不需要再发 HTTP request了,使得这个长连接变成了一个真.长连接。但是不需要发送 HTTP header就能交换数据显然和原有的 HTTP 协议是有区别的,所以它需要对服务器和客户端都进行升级才能实现。在此基础上 WebSocket 还是一个双通道的连接,在同一个 TCP 连接上既可以发也可以收信息。此外还有 multiplexing 功能,几个不同的 URI 可以复用同一个 WebSocket 连接。这些都是原来的 HTTP 不能做到的。

二、Socket.IO的使用

1. 直播视频的消息推送


先说说项目背景:公司的app里有直播,类似于新浪app的直播,而“直播后台监控系统”就是为了监控各个主播直播的情况,是否有不当言论等等,目前只有直播的视频画面,没有直播文字,所以需要增加文字监控。
“直播后台监控系统”后端java开发,一个监控页面可以监控4-8个直播间,直播视频采用了腾讯的播放器,传送地址 腾讯云视频点播服务的网页播放器(Web SDK)。 虽然api里有弹幕接口,经过仔细讨论,仍然决定采用Socket.IO来做,并且一个监控页面只建立一个socket链接,监控页面收到推送消息之后根据直播间的id,直接把消息append到对应直播间.

需求和思路说清楚了,现在直接贴代码:

首次先在页面上引入,从源码可以看到,socket.io-1.4.0.js已做了兼容,AMD和CMD规范都可以用,

<script src="http://cdn.socket.io/socket.io-1.4.0.js"></script>

此时,Socket.IO在此页面上是有效的,下面创建Socket并且绑定消息推送,

var socket = io.connect('http://XXX:9092');  //建立socket链接
    socket.on('connect', function () {  //当socket连接成功之后执行function里面的代码.
        socket.emit('registerMonitorRoomEvent', {  //注册监听事件,将需要监听的直播房间好发给后台.
                roomId : roomId
        });
    });
    socket.on('receiveMessageEvent', function (msg) {  //收到后端推送的直播消息.
           liveObj[msg.roomId].onMonitorMessage(msg); //liveObj是前端定义的对象,存储了所有直播间实例,liveObj[msg.roomId]取到了需要推送消息的直播间,再调用该直播间定义好的onMonitorMessage方法接受消息。
    })
    
    //如果需要断开直播,直接socket.disconnect();

是的,前端代码就是这么少。java小白一只,只能勉强看明白后端写了什么,不贴后端代码了。

2. 聊天室。


socket.io官网上的一个demo,服务端采用node,想要快速看到socket.io各个api效果的,此demo最快。项目传送 A simple chat demo for socket.io

ps: examples/chat/public/index.html文件里面的25行,引入的路径要为<script src="/socket.io/socket.io.js"></script>。

三、WebSocket参考资源

维基百科-WebSocket
socket.io官方文档
认识HTML5的WebSocket

相关推荐