WebSocket 的原理以及如何使用

2023-08-10  本文已影响0人  limengzhe

前言

WebSocket 是 HTML5 引入的一项重要特性,它允许在浏览器和服务器之间建立双向通信。

与 HTTP 请求-响应模式不同,WebSocket 允许在一个连接上进行持续的双向数据传输,而不需要频繁地建立和关闭连接。这使得 WebSocket 适用于实时性要求较高的应用,如聊天应用、实时广播、股票市场等。

WebSocket 协议标识是 ws(未加密)和 wss(加密),类似于 HTTP 的 httphttps

const socket = new WebSocket("ws://example.com/socket")

WebSocket 的特点

双向通信

WebSocket 允许在同一个连接上同时发送和接收数据,从而实现实时双向通信。

持久连接

一旦建立了 WebSocket 连接,它会保持打开状态,直到显式关闭连接。

低延迟

WebSocket 的双向通信性质使得数据传输更加即时,相比传统的 HTTP 请求,减少了通信延迟。

轻量级

与 HTTP 相比,WebSocket 协议头较小,减少了数据传输时的开销。

支持跨域

WebSocket 允许在不同域名之间进行通信,通过协议和安全措施确保通信安全性。

WebSocket 工作原理

  1. 握手阶段: 客户端发起一个 HTTP 请求到服务器,请求升级为 WebSocket 连接。服务器验证请求后,将连接升级为 WebSocket。

  2. 双向通信: 一旦 WebSocket 连接建立,客户端和服务器可以在任何时候互相发送数据。数据可以以帧的形式传输,每个帧可以是文本或二进制数据。

  3. 关闭连接: 任一方可以在任何时候关闭 WebSocket 连接,触发关闭握手。

WebSocket 的属性

readyState

WebSocket 有多个属性,其中 readyState 是最常用的,用来表示连接状态,它定义以下几个常量用来表示:

常量 说明
WebSocket.CONNECTING 0 表示正在连接中。
WebSocket.OPEN 1 表示连接已建立,可以进行通信。
WebSocket.CLOSING 2 表示连接正在关闭。
WebSocket.CLOSED 3 表示连接已经关闭或者连接未成功。

示例代码:

console.log(WebSocket.CONNECTING) // 0
console.log(WebSocket.OPEN) // 1
console.log(WebSocket.CLOSING) // 2
console.log(WebSocket.CLOSED) // 3

const socket = new WebSocket("ws://example.com/socket")

socket.onopen = event => {
  console.log(socket.readyState) // 1
}

当然除了 readyState 还有一些别的属性,但不常用,这里不做过多介绍。如果需要请参考:WebSocket - Web API 接口参考 | MDN

WebSocket 的四个事件

open

连接建立时触发

const socket = new WebSocket("ws://example.com/socket")

// 当连接建立时
socket.onopen = event => {
  console.log("WebSocket connection established.")
}

// 或者
socket.addEventListener("open", function (event) {
  console.log("WebSocket connection established.")
})

message

客户端接收服务端数据时触发

const socket = new WebSocket("ws://example.com/socket")

// 当收到消息时
socket.onmessage = event => {
  console.log("Message from server ", event.data)
}

// 或者
socket.addEventListener("message", function (event) {
  console.log("Message from server ", event.data)
})

error

通信发生错误时触发

const socket = new WebSocket("ws://example.com/socket")

socket.onerror = error => {
  console.error("WebSocket error: " + error)
}

close

连接关闭时触发

const socket = new WebSocket("ws://example.com/socket")
socket.onclose = event => {
  console.log("WebSocket connection closed: " + event.code + " " + event.reason)
}

WebSocket 的两个方法

Socket.send()

使用连接发送数据

// 创建 WebSocket 连接
const socket = new WebSocket("ws://example.com/socket")

socket.send("Client Message")

Socket.close()

关闭连接

// 创建 WebSocket 连接
const socket = new WebSocket("ws://example.com/socket")

// 关闭 WebSocket 连接
socket.close()

// 关闭 WebSocket 连接并指定状态码和原因
socket.close(1000, "Connection closed by user")

前端完整使用示例

<!DOCTYPE html>
<html>
  <head>
    <title>WebSocket Example</title>
  </head>
  <body>
    <h1>WebSocket Example</h1>
    <div id="messages"></div>

    <script>
      // 创建 WebSocket 连接
      const socket = new WebSocket("ws://example.com/socket")

      // 当连接建立时
      socket.onopen = event => {
        console.log("WebSocket connection established.")
      }

      // 当收到消息时
      socket.onmessage = event => {
        console.log("Message from server ", event.data)
      }

      // 当连接关闭时
      socket.onclose = event => {
        console.log("WebSocket connection closed: " + event.code + " " + event.reason)
      }

      // 当发生错误时
      socket.onerror = error => {
        console.error("WebSocket error: " + error)
      }

      // 发送消息
      function sendMessage() {
        const message = prompt("Enter a message:")
        if (message) {
          socket.send(message)
        }
      }

      // 关闭 WebSocket 连接
      socket.close()

      // 关闭 WebSocket 连接并指定状态码和原因
      socket.close(1000, "Connection closed by user")
    </script>
  </body>
</html>

WebSocket 的心跳机制

心跳机制是一种民间说法,不是必须的,目的是为了保持 WebSocket 连接,防止连接意外断开的一种机制。一般通过定期发送小型数据包(称为心跳包或 ping)来维持 WebSocket 连接,以确保连接不会因为长时间没有数据传输而被关闭。

以下是 WebSocket 心跳机制的基本原理:

  1. 定时发送心跳包: 客户端和服务器都会定期发送心跳包,通常是一个空的或含有很少数据的消息,例如一个单字节的数据。这些心跳包的目的是告诉对方连接仍然活跃。

  2. 监测响应: 一旦一方发送了心跳包,另一方会回复一个响应(称为 pong),以表示连接正常。

  3. 检测连接状态: 如果一方在预定的时间内未收到心跳包或响应,就可以推断连接可能出现问题。在这种情况下,可以采取措施来重新建立连接或处理连接断开的情况。

示例代码:

<!DOCTYPE html>
<html>
  <head>
    <title>WebSocket Heartbeat Example</title>
  </head>
  <body>
    <h1>WebSocket Heartbeat Example</h1>

    <script>
      const ws = new WebSocket("wss://example.com/socket") // 替换为实际的WebSocket地址

      // 心跳间隔(毫秒)
      const heartbeatInterval = 5000 // 每5秒发送一次心跳包

      // 定时发送心跳包
      const heartbeat = () => {
        if (ws.readyState === WebSocket.OPEN) {
          console.log("Sending heartbeat")
          ws.send("heartbeat")
        }
      }

      ws.addEventListener("open", event => {
        console.log("WebSocket connection established.")

        // 开始定时发送心跳包
        setInterval(heartbeat, heartbeatInterval)
      })

      ws.addEventListener("message", event => {
        if (event.data === "pong") {
          console.log("Received pong response.")
        } else {
          console.log("Received message:", event.data)
        }
      })

      ws.addEventListener("close", event => {
        console.log("WebSocket connection closed:", event.code, event.reason)
      })

      ws.addEventListener("error", error => {
        console.error("WebSocket error:", error)
      })
    </script>
  </body>
</html>

WebSocket 和 HTTP/2 有什么异同点

WebSocket 和 HTTP/2 都支持 双向通信,但有所区别。

用途

通信模式

连接维持

总结

WebSocket 使用 HTTP 协议进行连接,然后升级为 WebSocket 协议。在需要双向通信的应用场景下非常有用,实时性非常高且不受跨域限制。


参考文档

上一篇 下一篇

猜你喜欢

热点阅读