socket
WebSocket
在html5之前,因为http协议是无状态的,要实现浏览器与服务器的实时通讯,如果不使用 flash、applet 等浏览器插件的话,就需要定期轮询服务器来获取信息。这造成了一定的延迟和大量的网络通讯。随着HTML5 的出现,这一情况有望彻底改观,它就是WebSocket。
WebSocket的工作机制
浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。因为 WebSocket 连接本质上就是一个 TCP 连接,所以在数据传输的稳定性和数据传输量的大小方面,和传统轮询以技术比较,具有很大的性能优势。
为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息”Upgrade: WebSocket”表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。

这是一个握手的http请求,它与普通的http请求有一些区别,首先请求和响应的,”Upgrade:WebSocket”表示请求的目的就是要将客户端和服务器端的通讯协议从 HTTP 协议升级到 WebSocket 协议。从客户端到服务器端请求的信息里包含有”Sec-WebSocket-Extensions”、“Sec-WebSocket-Key”这样的头信息。这是客户端浏览器需要向服务器端提供的握手信息,服务器端解析这些头信息,并在握手的过程中依据这些信息生成一个 28 位的安全密钥并返回给客户端,以表明服务器端获取了客户端的请求,同意创建 WebSocket 连接。
从握手的协议可以看出,如果我们要使用WebSocket,我们需要一个实现Websocket协议规范的服务器。
值得一提的是:websocket是可以和http共用监听端口的,也就是它可以公用端口完成socket任务。
socket.io
socket.io封装了websocket,同时包含了其它的连接方式,比如Ajax。 原因在于不是所有的浏览器都支持websocket,通过socket.io的封装,你不用关心里面用了什么连接方式。 你在任何浏览器里都可以使用socket.io来建立异步的连接。socket.io包含了服务端和客户端的库, 如果在浏览器中使用了socket.io的js,服务端也必须同样适用。 如果你很清楚你需要的就是websocket,那可以直接使用websocket。
socket.io 安装
npm: npm i socket.io-client
直接引入: <script src='https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js'></script>
socket.io API使用(客户端)
npm socket.io 引入
import io from 'socket.io-client';
创建连接
const socket = io(url, { //指定后台的url地址
path: config.socketPath, //子路径
transports: ['websocket', 'polling'],
query: {
token: Cookie.get(config.cookie.auth)
}
});
io.connect(uri, [options]); 这是创建连接的方法,主要看一下可选的第二个参数,从源码中我们可以看到默认设置有哪些:
this.options = {
'port': 80,
'secure': false,
'document': 'document' in global ? document : false,
'resource': 'socket.io',
'transports': io.transports,
'connect timeout': 10000,
'try multiple transports': true,
'reconnect': true,
'reconnection delay': 500,
'reconnection limit': Infinity,
'reopen delay': 3000,
'max reconnection attempts': 10,
'sync disconnect on unload': false,
'auto connect': true,
'flash policy port': 10843,
'manualFlush': false
};
主要介绍几个我能看懂的,也比较常用的:
connect timeout
默认值: 5000
作用:设置创建连接所接收的超时时间,单位是毫秒。
try multiple transports
默认值: true
作用:当连接超时后是否允许Socket.io以其他连接方式尝试连接
reconnect 默认值: true
作用:当连接终止后,是否允许Socket.io自动进行重连
reconnection delay 默认值: 500
作用:为Socket.io的重连设置一个时间间隔,内部会在多次重连尝试时采用该值的指数值间隔,用来避免性能损耗(500 > 1000 > 2000 > 4000 > 8000)
max reconnection attempts 默认值: 10
作用:设置一个重连的最大尝试次数,超过这个值后Socket.io会使用所有允许的其他连接方式尝试重连,直到最终失败。
transports 默认值: ['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling']
作用:默认支持的链接方式(顺序敏感)
socket 正在重连
socket.on('reconnecting',function(msg) {
console.log('网络正在重连中...');
})
socket 重连成功
socket.on('reconnect',function(msg) {
console.log('网络重连成功!');
})
socket 监听服务器消息,message是前端后端约定好的客户端监听事件名称,msg是监听服务器返回的数据
socket.on('message', msg => {})
socket 向服务器发送消息,message是前端后端约定好的服务器监听事件名称,data是发送给服务器的数据
let data = {}
socket.emit('message',data)
socket 断开连接
socket.disconnect()
Notification API
HTML5 Web Notification通知是属于桌面性质的通知,有点类似于显示器右下角蹦出的QQ弹框,杀毒提示之类的,跟浏览器是脱离的,消息是置顶的。
在应用可以发送通知之前,用户必须授予应用有权这么做。这是一个常见的要求,当一个 API 至少一次试图与 web 页外部进行交互时,用户不得不专门授予该应用程序有权限提出通知,从而让用户控制允许哪些应用程序或网站显示通知。
你可以通过检查只读属性 Notification.permission 的值来查看你是否已经有权限。该属性的值将会是下列三个之一:
default 用户还未被询问是否授权,所以通知不会被显示。
granted 表示之前已经询问过用户,并且用户已经授予了显示通知的权限。
denied 用户已经明确的拒绝了显示通知的权限。
如果权限尚未被授予,那么应用不得不通过 Notification.requestPermission() 方法让用户进行选择。这个方法接受一个回调函数,一旦用户回应了显示通知的请求,将会调用这个函数。
if (window.Notification && Notification.permission !== "granted") {
Notification.requestPermission(function (status) {
if (Notification.permission !== status) {
Notification.permission = status;
}
});
}
实例属性
-
Notification.title 只读 (moz only) 在构造方法中指定的 title 参数。
-
Notification.dir 只读 通知的文本显示方向。在构造方法的 options 中指定。
-
Notification.lang 只读 通知的语言。在构造方法的 options 中指定。
-
Notification.body 只读 通知的文本内容。在构造方法的 options 中指定。
-
Notification.tag 只读 通知的 ID。在构造方法的 options 中指定。
-
Notification.icon 只读 通知的图标图片的 URL 地址。在构造方法的 options 中指定。
事件处理 -Notification.onclick
处理 click 事件的处理。每当用户点击通知时被触发。
-
Notification.onshow 处理 show 事件的处理。当通知显示的时候被触发。
-
Notification.onerror 处理 error 事件的处理。每当通知遇到错误时被触发。
-
Notification.onclose 处理 close 事件的处理。当用户关闭通知时被触发。
方法
-Notification.close() 用于关闭通知。 Notification 对象继承自 EventTarget 接口。
demo
let msg = {
"sender": "访客 64082",
"channel":3,
"type":4,
"data":"你好,我是桌面提醒!",
}
Notification.requestPermission().then(function (result) {
if (result === 'denied') {
console.log('Permission wasn\'t granted. Allow a retry.');
return false;
}
if (result === 'default') {
console.log('The permission request was dismissed.');
return false;
}
let typeList = ['[视频]', '[图片]', '[文件]', '[语音]']
var listenMessage = new Notification(msg.sender + " 说:", {
body: msg.type === 4 ? msg.data.length > 18 ? msg.data.substr(0, 18) + '...' : msg.data : typeList[msg.type],
tag: 'listenMessage',
icon: 'assets/img/favicon.ico',
}); // 显示通知
<!--点击桌面提醒时操作-->
listenMessage.onclick = function () {
window.focus();
listenMessage.close();
// hashHistory.push('/home/socket/socketMgmt')
};
});
