javascript websocket[心跳+服务端向前端推送信息]

一、【作用】
为了保持连接的可持续性和稳定性,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通道进行数据传输。
三次握手
第一次握手:客户端发数据给服务端,等待确认。
第二次握手:服务端收到数据,重新发确认数据到客户端确认连接请求。
第三次握手:客户端收到服务端确认,发数据给服务器告知可以建立连接了。
问:为什么是三次握手?
答:三次握手建立连接,是为了确保通信双方都具有收发数据的能力。
两次不安全,四次没必要。
javascript websocket[心跳+服务端向前端推送信息]
四次挥手
第一次挥手,客户端发送关闭相关的数据到服务端,并进入等待状态;
第二次挥手,服务端收到关闭相关的数据后,给客户端发送确认序号,服务端进入关闭等待状态;
第三次挥手,服务端再次发送关闭server到client的相关数据到客户端,并进入LAST_ACK状态。
第四次挥手:客户端收到关闭server到client数据后,进入TIME_WAIT状态,接着发送确认号给服务端。服务端最终关闭。
javascript websocket[心跳+服务端向前端推送信息]
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>

八、上图
1、服务端客户端握手成功

javascript websocket[心跳+服务端向前端推送信息]

2、第一次服务器推送数据
javascript websocket[心跳+服务端向前端推送信息]

3、第二次服务器推送数据
javascript websocket[心跳+服务端向前端推送信息]

4、后续哪个漫长的等待
javascript websocket[心跳+服务端向前端推送信息]

猜你喜欢

转载自blog.51cto.com/13479739/2483080
今日推荐