websocket

WebSocket是一种提供持久连接的协议,允许服务器主动向客户端推送信息,解决了HTTP单向请求的问题。它建立在TCP之上,兼容HTTP,通常用于需要实时交互的应用,如聊天室。WebSocket连接通过HTTP握手完成,握手时需要特定的头部字段,如Upgrade和Sec-WebSocket-Key。一旦建立连接,双方即可双向通信。心跳包机制用于检测并维持连接的稳定性,防止网络断开时数据丢失。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. websocket背景

由于HTTP 协议有一个明显的缺陷:通信只能由客户端发起。
举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。

这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就只能使用"轮询":每隔一段时候,就发出一个请求,了解服务器有没有新的信息。最典型的场景就是聊天室。轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。

WebSocket 就是基于这种场景诞生的。

2. websocket特点

websocket协议是一种浏览器的API,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接, 并进行全双工、双向数据传输。
在这里插入图片描述
在这里插入图片描述
webSockets特点:

  1. 与http一样,建立在 TCP 协议之上,本质上一种计算机网络应用层的协议,用来弥补http协议在持久通信能力上的不足。
  2. 服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
  3. 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  4. 数据格式比较轻量,性能开销小,通信高效。
  5. 可以发送文本,也可以发送二进制数据。
  6. 没有同源限制,客户端可以与任意服务器通信。
  7. 使用了自定义协议,协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

    例:
    ws://example.com:80/some/path
    wss://example.com:443/some/path

在这里插入图片描述

3. websocket基本使用

websocket基本使用

const url = "wss://echo.websocket.org"
// 创建WebSockt,实例一个对象,并传入要链接的url,执行该句之后,客户端就会与服务器进行连接。
var ws = new WebSocket(url);

ws.onopen = function(evt) { 
  console.log("Connection open ..."); 
  // send()方法发送数据
  ws.send("Hello WebSockets!");
};
// 服务器发来的消息时,会触发message事件
ws.onmessage = function(evt) {
  console.log( "Received Message: " + evt.data);
  ws.close();
};

ws.onclose = function(evt) {
  console.log("Connection closed.");
};  
// 在发生错误时触发error事件,连接不能持续
ws.onerror = function(){
	alter("发生错误");
}

4. websocket原理

  1. HTTP1.0 :一个 Request 一个 Response

  2. HTTP1.1(使用 keep-alive):在一个 HTTP 连接中,可以发送多个 Request,接收多个 Response, 并且Request = Response,也就是说一个 Request 只能有一个 Response。

  3. WebSocket连接的过程是:
    首先,客户端发起http请求,经过3次握手后,建立起TCP连接;http请求里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等;
    然后,服务器收到客户端的握手请求后,同样采用HTTP协议回馈数据;
    最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行WebSocket全双工通信。

  4. 首先我们来看个典型的 WebSocket 握手

    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
    Sec-WebSocket-Protocol: chat, superchat
    Sec-WebSocket-Version: 13
    Origin: http://example.com
    

    其中:

    Upgrade: websocket
    Connection: Upgrade
    

    这个就是 WebSocket 的核心了,告诉 Apache 、 Nginx 等服务器将要发起的请求要用 WebSocket 协议了

    Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
    

    Sec-WebSocket-Key 是一个 Base64 encode 的值,这个是浏览器随机生成的,验证WebSocket服务器。Sec-WebSocket-Key 的生成算法是拼接服务端和客户端生成的字符串,进行SHA1哈希算法,再用base64编码。

    Sec-WebSocket-Protocol: chat, superchat
    

    Sec_WebSocket-Protocol 是一个用户定义的字符串,用来区分同 URL 下,不同的服务所需要的协议。

    Sec-WebSocket-Version: 13
    

    Sec-WebSocket-Version 是告诉服务器所使用的 WebSocket 协议版本

    然后服务器会返回下列东西,表示已经接受到请求, 成功建立 WebSocket 啦!

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
    Sec-WebSocket-Protocol: chat
    

    其中:

    Upgrade: websocket
    Connection: Upgrade
    

    告诉客户端即将升级的是 WebSocket 协议

    Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
    

    Sec-WebSocket-Accept 这个则是经过服务器确认,并且加密过后的 Sec-WebSocket-Key 。

    Sec-WebSocket-Protocol: chat
    

    Sec-WebSocket-Protocol 则是表示最终使用的协议。

    至此,HTTP 已经完成它所有工作了,接下来就是完全按照 WebSocket 协议进行了。

5. 心跳包机制

在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件。这样服务器会继续向客户端发送数据,并且这些数据还会丢失。所以就需要一种机制【心跳包机制】来检测客户端和服务端是否处于正常的链接状态,并且可用于维持长连接,保活。⼼跳包机制就是每隔⼀段时间会向服务器发送⼀个数据包,同时服务器端会回传⼀个数据包给客户端,来检测客户端和服务端是否处于正常的链接状态,否则的话,有可能是⽹络断开连接了。需要重连。

心跳包机制有2种方案:一种是客户端主动发送上行心跳包,另一种方案是服务端主动发送下行心跳包。

心跳检测步骤:

  1. 客户端每隔一个时间间隔发生一个探测包给服务器
  2. 客户端发包时启动一个超时定时器
  3. 服务器端接收到检测包,应该回应一个包
  4. 如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器
  5. 如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了
// 前端解决方案:心跳检测
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);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值