赞
踩
一、【作用】
为了保持连接的可持续性和稳定性,websocket心跳就是解决这个问题的。
二、【剖析】
1、如果设备网络断开,原生websocket不会立即触发websocket任何事件,前端也无法得知当前连接是否已经断开。
2、我们使用websocket.send方法时,浏览器才会发现连接断开了。便会触发onclose方法。
3、同样后端websocket服务也可能造成连接断开,前端也不会收到断开的通知,因此需要前端定时发送心跳消息【ping】,后端收到ping类型的消息返回【pong】消息,告知前端连接正常。反之连接断开。
三、【原理】
以前端最为主动方,定时发送ping消息的方式就是浏览器心跳机制。
四、【websocket和socket区别】
websocket是H5一种新协议。它实现了浏览器与服务器双通信。建立握手动作还是需要借助http请求完成。
http协议是非持久化的,单向的网络协议。在建立连接连接后只允许浏览器发出请求,服务器才能返回相应的数据。浏览器不断的发送请求,而且请求的Header也比较长:浪费流量、服务器资源
即时通讯在网站上是很常见的,比如网页QQ等。之前通常采用的方式是轮询、Comet技术实现。
websocket就可以解决这一点。只需要服务器和浏览器通过http协议进行握手动作,然后单独建立一条tcp通信通道进行数据传送。
握手动作
浏览器、服务器建立tcp连接的三次握手,是通信的基础;
tcp连接成功后,浏览器通过http协议,向服务器传送websocket支持的版本信息;
服务器收到客户端的握手请求后,同样采用http洗衣反馈数据;
客户端收到连接成功消息后,以后采用tcp通道进行数据传输。
三次握手
第一次握手:客户端发数据给服务端,等待确认。
第二次握手:服务端收到数据,重新发确认数据到客户端确认连接请求。
第三次握手:客户端收到服务端确认,发数据给服务器告知可以建立连接了。
问:为什么是三次握手?
答:三次握手建立连接,是为了确保通信双方都具有收发数据的能力。
两次不安全,四次没必要。
四次挥手
第一次挥手,客户端发送关闭相关的数据到服务端,并进入等待状态;
第二次挥手,服务端收到关闭相关的数据后,给客户端发送确认序号,服务端进入关闭等待状态;
第三次挥手,服务端再次发送关闭server到client的相关数据到客户端,并进入LAST_ACK状态。
第四次挥手:客户端收到关闭server到client数据后,进入TIME_WAIT状态,接着发送确认号给服务端。服务端最终关闭。
socket其实不是一个协议,而是为了方便使用tcp或者udp而抽象出来的一个层次。是在应用层和传输层之间的一组接口。当两台主机通信时,必须通过Socket连接,Socket则利用TCP/IP协议建立TCP连接。TCP连接则更依靠于底层的IP协议,IP协议的连接则依赖于链路层等更低层次。
五、示例
- 客户端websocket示例:
- //1、申请一个Websocket对象,参数是需要连接服务端的地址,同 HTTP 协议开头一样,WebSocket 协议的 URL 使用 ws://开头,另外安全的 WebSocket 协议使用 wss://开头。
- var ws = new WebSocket(“ws://echo.websocket.org”);
- //WebSocket 对象一共支持四个消息 onopen, onmessage, onclose 和 onerror
- ws.onopen = function(){ws.send(“Test!”); };
- ws.onmessage = function(evt){console.log(evt.data);ws.close();};
- ws.onclose = function(evt){console.log(“WebSocketClosed!”);};
- ws.onerror = function(evt){console.log(“WebSocketError!”);};
当浏览器和服务端连接成功后,会触发onop嗯消息,
如果失败,会触发onerror消息。
当浏览器收到服务端发送过来的数据时会触发onmessage消息,
当浏览器收到服务端发送关闭连接请求时,会触发onclose消息。
所有的操作都是才送一步回调的方式触发。
六、后端代码
- //开启WebSocket支持
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.socket.server.standard.ServerEndpointExporter;
-
- @Configuration
- public class WebSocketConfig {
- @Bean
- public ServerEndpointExporter serverEndpointExporter() {
- return new ServerEndpointExporter();
- }
- }
-
- import org.springframework.stereotype.Component;
- import javax.websocket.*;
- import javax.websocket.server.ServerEndpoint;
-
- /**
- * Frozen
- * 2020年3月30日21:22:55
- */
- @ServerEndpoint("/redant")
- @Component
- public class FrozenTest {
- /**
- * 正常连接
- * @throws Exception
- */
- @OnOpen
- public void onOpen(Session session) throws Exception {
- sendMessage(session, "我还是从前哪个少年");
- Thread.sleep(10000);//10秒后再发个
- sendMessage(session, "嗨,HoYL,这是10秒之后的服务器推送数据!");
- Thread.sleep(5000);//10秒后再发个
- for (int i = 0; i < 100; i++) {
- Random random = new Random();
- sendMessage(session, String.valueOf(Math.random()*1000));
- Thread.sleep(5000);//10秒后再发个
- }
- }
- /**
- * 实现服务器主动推送
- */
- public void sendMessage(Session session, String message) throws Exception {
- session.getBasicRemote().sendText(message);
- }
- }

七、前端测试代码
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8">
- <title>心跳测试</title>
- <script type="text/javascript" src="frozenjs/websocket.js" ></script>
- <script type="text/javascript" src="frozenjs/jquery-1.10.2.min.js" ></script>
- </head>
- <body>
- <div>
- <span id="suppose" style="color: red; font-weight: bolder;"></span>
- </div>
- </body>
- <script>
- var url = "ws://127.0.0.1:8088/rest/2020/redant";
- var ws = new WebSocket(url);
- ws.onclose = function (e) {
- };
- ws.onerror = function (e) {
- };
-
- ws.onopen = function () {
- alert("与服务器连接成功!");
- };
- ws.onmessage = function (event) {
- $("#suppose").text(event.data);
- }
-
- </script>
- </html>

赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。