基本概念
WebSocket 是基于 TCP 的一种新的应用层网络协议。它提供了一个全双工的通道,允许服务器和客户端之间实时双向通信。因此,在 WebSocket 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,客户端和服务器之间的数据交换变得更加简单。
优点
- 更高的实时性能:WebSocket 允许服务器和客户端之间实时双向通信,从而提高了实时通信场景中的性能。
- 更少的网络开销: HTTP请求和响应之间需要额外的数据传输,而 WebSocket 通过在同一个连接上双向通信,减少了网络开销。
- 更灵活的通信方式:HTTP请求和响应通常是一一对应的,而 WebSocket 允许服务器和客户端之间以多种方式进行通信,例如消息 Push、事件推送等。
- 更简洁的 API:WebSocket 提供了简洁的 API,使得客户端开发人员可以更轻松地进行实时通信。
缺点
- 不支持无连接: WebSocket是一种持久化的协议,这意味着连接不会在一次请求之后立即断开。这是有利的,因为它消除了建立连接的开销,但是也可能导致一些资源泄漏的问题。
- 不支持广泛: WebSocket 是 HTML5中的一种标准协议,虽然现代浏览器都支持,但是一些旧的浏览器可能不支持WebSocket。
- 需要特殊的服务器支持: WebSocket 需要服务端支持,只有特定的服务器才能够实现
WebSocket协议。这可能会增加系统的复杂性和部署的难度。- 数据流不兼容: WebSocket 的数据流格式与 HTTP不同,这意味着在不同的网络环境下,WebSocket 的表现可能会有所不同。
工作流程
1.握手阶段
WebSocket在建立连接时需要进行握手阶段。握手阶段包括以下几个步骤:
1.客户端向服务端发送请求,请求建立WebSocket连接。请求中包含一个Sec-WebSocket-Key参数,用于生成WebSocket的随机密钥。
2.服务端接收到请求后,生成一个随机密钥,并使用随机密钥生成一个新的Sec-WebSocket-Accept参数。
- 客户端接收到服务端发送的新的Sec-WebSocket-Accept参数后,使用原来的随机密钥和新的Sec-WebSocket-Accept参数共同生成一个新的Sec-WebSocket-Key参数,用于加密数据传输。
4.客户端将新的Sec-WebSocket-Key参数发送给服务端,服务端接收到后,使用该参数加密数据传输。
2.数据传输
建立连接后,客户端和服务端就可以通过WebSocket进行实时双向通信。数据传输阶段包括以下几个步骤:
客户端向服务端发送数据,服务端收到数据后将其转发给其他客户端。
服务端向客户端发送数据,客户端收到数据后进行处理。
3.关闭阶段
当不再需要WebSocket连接时,需要进行关闭阶段。关闭阶段包括以下几个步骤:
客户端向服务端发送关闭请求,请求中包含一个WebSocket的随机密钥。
服务端接收到关闭请求后,向客户端发送关闭响应,关闭响应中包含服务端生成的随机密钥。 客户端收到关闭响应后,关闭WebSocket连接。
JavaScript 中 WebSocket 对象的属性和方法,以及如何创建和连接 WebSocket。
WebSocket 对象的属性和方法:
WebSocket 对象:WebSocket 对象表示一个新的 WebSocket 连接。
WebSocket.onopen 事件处理程序:当 WebSocket 连接打开时触发。
WebSocket.onmessage 事件处理程序:当接收到来自 WebSocket 的消息时触发。
WebSocket.onerror 事件处理程序:当 WebSocket 发生错误时触发。
WebSocket.onclose 事件处理程序:当 WebSocket 连接关闭时触发。
WebSocket.send 方法:向 WebSocket 发送数据。
WebSocket.close 方法:关闭 WebSocket 连接。
创建和连接 WebSocket:
创建 WebSocket 对象:
javascript
var socket = new WebSocket('ws://example.com');
其中,ws://example.com 是 WebSocket 的 URL,表示要连接的服务器。
连接 WebSocket:
使用 WebSocket.onopen 事件处理程序检查 WebSocket 是否成功连接。
javascript
socket.onopen = function() {
console.log('WebSocket connected');
};
接收来自 WebSocket 的消息:
使用 WebSocket.onmessage 事件处理程序接收来自 WebSocket 的消息。
javascript
socket.onmessage = function(event) {
console.log('WebSocket message:', event.data);
};
向 WebSocket 发送消息:
使用 WebSocket.send 方法向 WebSocket 发送消息。
javascript
socket.send('Hello, WebSocket!');
关闭 WebSocket:
javascript
socket.close();
注意:
在 WebSocket 连接成功打开和关闭时,会分别触发 WebSocket.onopen 和 WebSocket.onclose 事件。在接收到来自 WebSocket 的消息时,会触发 WebSocket.onmessage 事件。当 WebSocket 发生错误时,会触发 WebSocket.onerror 事件。
WebSocket 错误处理
WebSocket is not supported:当浏览器不支持 WebSocket 时,会出现此错误。解决方法是在浏览器兼容性列表中检查是否支持 WebSocket。
WebSocket connection closed:当 WebSocket 连接被关闭时,会出现此错误。解决方法是在 WebSocket.onclose 事件处理程序中进行错误处理。
WebSocket error:当 WebSocket 发生错误时,会出现此错误。解决方法是在 WebSocket.onerror 事件处理程序中进行错误处理。
WebSocket timeout:当 WebSocket 连接超时时,会出现此错误。解决方法是在 WebSocket.ontimeout 事件处理程序中进行错误处理。
WebSocket handshake error:当 WebSocket 握手失败时,会出现此错误。解决方法是在 WebSocket.onerror 事件处理程序中进行错误处理。
WebSocket closed by server:当 WebSocket 连接被服务器关闭时,会出现此错误。解决方法是在 WebSocket.onclose 事件处理程序中进行错误处理。
WebSocket closed by protocol:当 WebSocket 连接被协议错误关闭时,会出现此错误。解决方法是在 WebSocket.onclose 事件处理程序中进行错误处理。
WebSocket closed by network:当 WebSocket 连接被网络错误关闭时,会出现此错误。解决方法是在 WebSocket.onclose 事件处理程序中进行错误处理。
WebSocket closed by server:当 WebSocket 连接被服务器错误关闭时,会出现此错误。解决方法是在 WebSocket.onclose 事件处理程序中进行错误处理。
心跳检测
理解:
它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
心跳检测步骤:
javascript
// 前端解决方案:心跳检测
var heartCheck = {
timeout: 30000, //30秒发一次心跳
timeoutObj: null,
serverTimeoutObj: null,
reset: function(){
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function(){
var self = this;
this.timeoutObj = setTimeout(function(){
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
ws.send('ping');
console.log('ping!')
self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
ws.close(); //如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
}, self.timeout);
}, this.timeout);
}
}
客户端每隔一个时间间隔发生一个探测包给服务器
客户端发包时启动一个超时定时器
服务器端接收到检测包,应该回应一个包
如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器
如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了