程序员WEB前端程序开发让前端飞

WebSocket探索

2017-12-08  本文已影响0人  坤少卡卡

最近在项目中使用了WebSocket进行长连接通信,本文就简要的记录一下所用到的东西。

首先我们先学习几个概念:
长连接
一个连接上可以连续发送多个数据包,在连接期间,如果没有数据包发送,需要双方发链路检查包。
TCP/IP
TCP/IP属于传输层,主要解决数据在网络中的传输问题,只管传输数据。但是那样对传输的数据没有一个规范的封装、解析等处理,使得传输的数据就很难识别,所以才有了应用层协议对数据的封装、解析等,如HTTP协议。
HTTP
HTTP是应用层协议,封装解析传输的数据。从HTTP1.1开始其实就默认开启了长连接,也就是请求header中看到的Connection:Keep-alive。但是这个长连接只是说保持了(服务器可以告诉客户端保持时间Keep-Alive:timeout=200;max=20;)这个TCP通道,直接Request - Response,而不需要再创建一个连接通道,做到了一个性能优化。但是HTTP通讯本身还是Request - Response。
socket
与HTTP不一样,socket不是协议,它是在程序层面上对传输层协议(可以主要理解为TCP/IP)的接口封装。
我们知道传输层的协议,是解决数据在网络中传输的,那么socket就是传输通道两端的接口。所以对于前端而言,socket也可以简单的理解为对TCP/IP的抽象协议。
WebSocket
WebSocket是包装成了一个应用层协议作为socket,从而能够让客户端和远程服务端通过web建立全双工通信。websocket提供ws和wss两种URL方案。

WebSocket API


接下来我们再来看看WebSocket的API。首先我们需要做的就是创建一个实例:

const wsUri = 'ws://zhhy-screen.ums86.com/webSocket/memberId/pc';

let websocket  = new WebSocket(wsUri);//创建WebSocket

因为项目中要涉及到重连机制,所以就使用了ReconnectingWebSocket这个插件,用法也十分简单,在需要创建ws实例的页面引入插件:

import ReconnectingWebSocket from './js/reconnecting-websocket.min'
// 具体的路径根据具体项目而定

let websocket  = new ReconnectingWebSocket(wsUri);
// 然后直接将创建实例的语句写成这样就可以了。

WebSocket 事件

该事件是在服务器相应WebSocket连接请求触发。

websocket.onopen = (evt) => {
    let val = 'message';
    websocket.send(JSON.stringify(val));
};

该事件是服务器有响应信息的时候触发。

websocket.onmessage = (evt) => {
    console.log(evt.data);
};
  //实际项目中就是在此事件中获取返回的数据的。

该事件是出错时触发,并且会关闭连接。

websocket.onerror = (evt) => {
    console.log('error');    
}

连接关闭时触发,这在两端都可以关闭。另外如果连接失败也是会触发的。

websocket.onclose = function(evt) {
    console.log("Connection closed.");
};  

WebSocket 方法

if (websocket.readyState === WebSocket.OPEN) {
    websocket.send(JSON.stringify(val));
}

该方法用来主动关闭连接。

websocket.close();

上面出现的readyState就是ws实例的当前状态,一共有4种:

所以可以根据websocket.readyState === WebSocket.OPEN来判断是否连接成功。

下面我们再来看看建立ws实例的时候,浏览器的请求和相应:

Request URL:ws://zhhy-screen.ums86.com/webSocket/memberId/pc
Request Method:GET
Status Code:101  //状态码为101表示切换协议

Response Headers

Connection:upgrade
Content-Type:application/octet-stream
Date:Fri, 08 Dec 2017 02:20:11 GMT
Sec-WebSocket-Accept:M2OEhXpd4zqIkjEQtUsEr0ZSJWs= //服务器端将加密处理后的握手Key通过这个字段返回给客户端表示服务器同意握手建立连接。
Sec-WebSocket-Extensions:permessage-deflate;client_max_window_bits=15
Server:Flaginfo_Web
ufe-result:A2
Upgrade:websocket

Request Headers

Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.9,en;q=0.8,fr;q=0.7
Cache-Control:no-cache
Connection:Upgrade //告知服务器当前请求连接是升级的。
Cookie:_qddaz=QD.f47rqu.5a3mle.j9tqibli
Host:zhhy-screen.ums86.com
Origin:http://localhost:8083
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:jo9tTVEKTIC4UXR4HZpZMQ== //为了表示服务器同意和客户端进行Socket连接,服务器端需要使用客户端发送的这个Key进行校验,然后返回一个校验过的字符串给客户端,客户端验证通过后才能正式建立Socket连接。
Sec-WebSocket-Version:13 //版本,必须是13
Upgrade:websocket //告诉服务器这个HTTP连接是升级的Websocket连接。
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36 //客户端的浏览器信息,可以根据此字段判断浏览器版本和客户端类型

以上就是所掌握的所有websocket知识,同时项目中还涉及到了PC的不同页面主动向App推送消息,其中就用到了VUEX(项目是使用VUE框架进行开发)进行消息的监听与管理,不同页面通过commit消息this.$store.commit('sendData',data);,创建ws实例的页面进行监听,监听到消息的变化后,就通过ws的send()方法来向app推送消息,服务器端就起到一个中间人的作用。

参考文章:WebSocket探秘

上一篇下一篇

猜你喜欢

热点阅读