好的,我来给你做一份 WebSocket 详解,从概念、原理、协议、优缺点,到使用方法和示例都覆盖,方便你理解和应用。


1. WebSocket 是什么

WebSocket 是一种 在单个 TCP 连接上进行全双工通信的协议,由 HTML5 引入。它可以让客户端和服务器之间进行 实时双向数据传输,比传统 HTTP 更高效。

特点:

  1. 双向通信:客户端和服务器可以随时互相发送消息。
  2. 长连接:一次握手后保持连接,不需要每次请求都重新建立。
  3. 低延迟:减少 HTTP 请求头开销,实时性强。
  4. 轻量数据传输:消息帧小,适合实时应用。

2. WebSocket 与 HTTP 的区别

特性HTTPWebSocket
通信方式单向请求/响应双向通信
连接状态短连接,每次请求建立长连接,握手一次
实时性较低
数据传输效率需要频繁发送请求头消息帧小,开销低
适用场景普通网页访问聊天、游戏、股票行情、物联网

3. WebSocket 工作原理

3.1 建立连接

  1. 客户端发起 HTTP 升级请求(Upgrade)GET /chat HTTP/1.1 Host: server.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Version: 13
  2. 服务器响应升级成功: HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

3.2 数据传输

  • 连接建立后,客户端和服务器通过 消息帧(Frame) 发送数据。
  • WebSocket 支持 文本(UTF-8)二进制数据
  • 数据帧格式简单,开销低,实时性高。

3.3 关闭连接

  • 任意一方都可以发送 关闭帧(Close Frame)关闭连接。
  • 关闭时可带上状态码和原因。

4. WebSocket 协议细节

4.1 消息类型

类型描述
Text文本消息
Binary二进制消息
Close关闭连接
Ping心跳检测
Pong心跳响应

4.2 消息帧结构

WebSocket 帧包含:

  • FIN:是否为最后一帧
  • Opcode:操作码(如文本、二进制)
  • Mask:是否掩码(客户端必须对数据掩码)
  • Payload Length:负载长度
  • Payload Data:实际数据

5. WebSocket 优缺点

优点

  1. 双向通信,实时性强
  2. 长连接,减少握手开销
  3. 支持二进制数据
  4. 开发简单,可用 JavaScript 直接在浏览器中使用

缺点

  1. 需要浏览器或客户端支持
  2. 防火墙或代理可能阻塞 WebSocket
  3. 长连接占用资源
  4. 不适合传统请求/响应场景

6. WebSocket 使用示例

6.1 浏览器端(JavaScript)

// 创建 WebSocket 连接
const ws = new WebSocket("ws://localhost:8080/ws");

// 连接打开
ws.onopen = () => {
    console.log("Connected");
    ws.send("Hello Server!");
};

// 接收消息
ws.onmessage = (event) => {
    console.log("Received:", event.data);
};

// 关闭连接
ws.onclose = () => {
    console.log("Disconnected");
};

// 发生错误
ws.onerror = (err) => {
    console.error("Error:", err);
};

6.2 Go 语言服务器端

使用 github.com/gorilla/websocket 包:

package main

import (
    "fmt"
    "net/http"
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{}

func wsHandler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        fmt.Println("Upgrade error:", err)
        return
    }
    defer conn.Close()

    for {
        mt, message, err := conn.ReadMessage()
        if err != nil {
            fmt.Println("Read error:", err)
            break
        }
        fmt.Printf("Received: %s\n", message)
        err = conn.WriteMessage(mt, message)
        if err != nil {
            fmt.Println("Write error:", err)
            break
        }
    }
}

func main() {
    http.HandleFunc("/ws", wsHandler)
    fmt.Println("Server started at :8080")
    http.ListenAndServe(":8080", nil)
}

  • 功能:接收客户端消息并回显(Echo)。

7. WebSocket 应用场景

  1. 即时聊天系统:微信、Slack、聊天室
  2. 实时推送:股票行情、新闻推送
  3. 多人在线游戏
  4. 物联网设备通信
  5. 协作编辑:在线文档、白板