赞
踩
WebSocket的出现,使得浏览器具备了实时双向通信的能力。且它不在需要进行3次握手与4次挥手,只需要在客户端创建一个socket实例并且提供它所要连接服务端的IP地址和端口,而服务端创建另一个socket并绑定本地端口进行监听,然后客户端进行连接服务端,服务端接受连接之后双方建立了一个端对端的TCP连接,在该连接上就实现双向通讯了。本文由浅入深,介绍了WebSocket如何建立连接、交换数据的细节,以及数据帧的格式。此外,还简要介绍了针对WebSocket的安全攻击,以及协议是如何抵御类似攻击的。
浏览器发出webSocket的连线请求,服务器发出响应,这个过程称为握手,握手的过程只需要一次,就可以实现持久连接。
WebSocket 的工作原理如下:
WebSocket是真正的全双工通信机制,建立连接后客户端与服务器端是完全平等的,可以互相主动请求。而HTTP长连接基于HTTP,是传统的客户端对服务器发起请求的模式。 HTTP长连接中,每次数据交换除了真正的数据部分外,服务器和客户端还要大量交换HTTP header,消息交换效率低。Websocket协议通过第一个request建立了TCP连接之后,之后交换的数据都不需要发送 HTTP header就能交换数据,这显然和原有的HTTP协议有区别所以它需要对服务器和客户端都进行升级才能实现,当然在现在这个时代,我们的主流浏览器都是支持HTML5的,使用时我们直接使用即可。
WebSocket 协议本身是安全的,但你需要确保 WebSocket 连接是通过 HTTPS 协议建立的,以防止中间人攻击。在 Node.js 中,你可以使用 wss 模块来创建一个安全的 WebSocket 服务器。
//创建一个WebSocket服务器,在3000端口启动
const WebSocket = require('ws')
const server = new WebSocket.Server({port:3000})
wss:// 协议不仅是被加密的,而且更可靠。
因为 ws:// 数据不是加密的,对于任何中间人来说其数据都是可见的。并且,旧的代理服务器不了解 WebSocket,它们可能会因为看到“奇怪的” header 而中止连接。
另一方面,wss:// 是基于 TLS 的 WebSocket,类似于 HTTPS 是基于 TLS 的 HTTP),传输安全层在发送方对数据进行了加密,在接收方进行解密。因此,数据包是通过代理加密传输的。它们看不到传输的里面的内容,且会让这些数据通过。
只要有WebSocket连接到该服务器,就会触发’connection’事件;req对象可以用来获取客户端的信息,如ip、端口号
// 监听连接事件
server.on('connection',function connection(ws,req){
const ip = req.socket.remoteAddress
const port = req.socket.remotePort
const clientName = ip + port
console.log('%s is connected ',clientName)
})
server.on('connection',function connection(ws,req){
const ip = req.socket.remoteAddress
const port = req.socket.remotePort
const clientName = ip + port
// 发送消息到客户端
ws.send('Welcome ' + clientName)
})
send(data [,options][,callback])
data:发送的数据
options对象:
当客户端有消息发送给服务器时,服务器就能够触发该消息
server.on('connection',function connection(ws){
// 监听接收消息事件
ws.on('message',function incoming(message){
console.log('received: %s from %s',message,clientName)
server.clients.forEach(function each(client){
if(client.readyState === WebSocket.OPEN){
client.send(clientName +" -> " + message)
}
})
})
})
server.on('close',function close(){
console.log('disconnected')
})
创建了一个webScoket实例对象常用属性和方法的介绍
属性 | 说明 |
---|---|
url | 当前连接的webScoket接口地址 |
readyState | 当前连接的状态: 0:正在链接中 1:已经链接并且可以通讯 2:连接正在关闭 3;连接已关闭或者没有链接成功 |
onopen | 连接成功的回调函数 |
onerror | 连接失败的回调函数 |
onmessage | 从服务端接受到信息的回调函数 |
onclose | 连接关闭的回调函数 |
binaryType | 使用二进制的数据类型连接 |
protocol | 服务器选择的下属协议 |
bufferedAmount | 未发送至服务器的二进制字节数 |
close() | 关闭当前连接 |
send(data) | 发送消息到服务器 |
// 创建 WebSocket 连接 const ws = new WebSocket('ws://localhost:3000') // 连接打开时触发 ws.onopen = function () { console.log('我们连接成功啦...') // 发送消息到服务器 webSocket.send('Hello!') } // 连接出错时触发 ws.onerror = function () { console.log('连接失败了...') } // 接收到服务器消息时触发 ws.onmessage = function (e) { console.log('服务端传来数据啦...' + e.data) } // 连接关闭时触发 ws.onclose = function () { console.log('连接关闭了...') }
当我们正在使用WebScoket的时候,难免会出现WebScoket的断联,这个时候,我们只需要在onclose的回调函数中,重新链接即可
ws.onclose = function (e) {
// 1每10秒重连一次,直到连接成功
setTimeout(function () {
// 重新调用连接webSocket事件
ws = new WebSocket('ws://192.168.31.19:8081/')
ws.onopen = function () {
console.log('连接成功...')
}
}, 10000);
};
websocket长连接有默认的超时时间(1分钟),也就是说,超过一定的时间客户端和服务器之间没有发生任何消息传输,连接会自动断开;除此之外,服务器或防火墙一般也会在一段时间不活动并超时之后终止外部的长连接。因此,若需要使客户端一直保持连接,就需要设置心跳保活机制了。
实现原理:我们可以每次在 每次保持心跳保活的时候,向WebScoket发送一条消息,证明我们还"活着"
var timeout = 1000 * 30 //心跳间隔
var timeoutTimer=null //保持心跳的定时器
timeoutTimer = setTimeout(function () {
ws.send('HeartBeat')
}, timeout)
// 客户端主动断开连接
ws = new WebSocket('ws://192.168.31.19:8081/')
ws.close();
var ws = new WebSocket("ws://" + url );
ws.onopen=function(){
ws.send(token)
}
var ws = new WebSocket("wss://" + url?token );
websocket请求头中可以包含Sec-WebSocket-Protocol这个属性,该属性是一个自定义的子协议。它从客户端发送到服务器并返回从服务器到客户端确认子协议。我们可以利用这个属性添加token。
var ws = new WebSocket("ws://" + url,[token]);
例子包括了WebSocket服务端、WebSocket客户端。
Node使用ws创建WebSocket服务器
是一个用于支持WebSocket客户端和服务器的框架。它易于使用,功能强大,且不依赖于其他环境
npm install ws
启动3000端口。当有新的连接请求到达时,打印日志,然后延迟两次向客户端发送消息。当收到到来自客户端的消息时,同样打印日志。
server.js
var WebSocket = require('ws'); var wss = new WebSocket.Server({ port: 3000 }); // 创建一个TextDecoder实例来处理字符串 const decoder = new TextDecoder('utf-8'); wss.on('connection', function connection(ws) { console.log('server: receive connection.'); ws.on('message', function incoming(message) { console.log('server: received', decoder.decode(message)); }); let data1 = { name: 'zhangsan', age: 18 } let data2 = { name: 'lisi', age: 19 } let data3 = 'wangwu' sendData(ws, data1, 1000 * 60 * 1) sendData(ws, data2, 1000 * 60 * 2) sendData(ws, data3, 1000 * 60 * 3) }); const sendData = (ws, data = '', delay = 1000) => { if (!data) return if (typeof data === 'object') data = JSON.stringify(data) setTimeout(() => { ws.send(data); }, delay) }
向3000端口发起WebSocket连接。连接建立后,打印日志,同时向服务端发送消息。接收到来自服务端的消息后,同样打印日志。
app.vue
const ws = new WebSocket('ws://localhost:3000');
ws.onopen = function () {
console.log('我们连接成功了');
ws.send('hello');
};
ws.onmessage = function (e) {
console.log('服务端传来数据了:',e.data);
};
ws.onclose = function () {
console.log('连接关闭了');
};
ws.onerror = function (err) {
console.log('连接失败了', err);
};
可分别查看服务端、客户端的日志,这里不展开。
server: receive connection.
server: received hello
我们连接成功了
服务端传来数据了:{"name":"zhangsan","age":18}
服务端传来数据了:{"name":"lisi","age":19}
WebSocket 是一种强大的网络通信协议,它允许服务器和客户端之间进行实时、双向通信。在 WebSocket 连接中,服务器可以主动向客户端发送消息,这对于实时应用来说非常重要。通过使用 JavaScript 和后端语言,你可以轻松实现 WebSocket 通信。在实际应用中,WebSocket 已被广泛应用于在线聊天、股票交易、游戏等领域。
WebSocket 是一种在浏览器和服务器之间建立持久连接的现代方式。
WebSocket 方法:
WebSocket 事件:
WebSocket 自身并不包含重新连接(reconnection),身份验证(authentication)和很多其他高级机制。因此,有针对于此的客户端/服务端的库,并且也可以手动实现这些功能。
有时为了将 WebSocket 集成到现有项目中,人们将主 HTTP 服务器与 WebSocket 服务器并行运行,并且它们之间共享同一个数据库。对于 WebSocket 请求使用一个通向 WebSocket 服务器的子域 wss://ws.site.com,而 https://site.com 则通向主 HTTP 服务器。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。