gorilla/websocket 是一个非常流行的 Go 语言库,用于实现 WebSocket 协议的客户端和服务器端功能。它非常简洁且高效,支持多种高级功能,适合构建实时通信应用。下面我将详细讲解如何使用 gorilla/websocket 库,包含客户端和服务器端的使用方法、常见的差异,并提供基础和进阶教程。

基础使用

1. 安装 gorilla/websocket

首先需要安装 gorilla/websocket 库,可以使用 go get 命令来安装:

go get github.com/gorilla/websocket

2. 创建 WebSocket 服务器

WebSocket 服务器通常使用 http 包来处理客户端连接,gorilla/websocket 库提供了一个 Upgrader 类型来将 HTTP 请求升级为 WebSocket 连接。

WebSocket 服务器端示例

package main

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

// 定义 WebSocket 升级器,用于将 HTTP 请求升级为 WebSocket 连接
var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        // 允许任何来源的连接
        return true
    },
}

func handler(w http.ResponseWriter, r *http.Request) {
    // 升级 HTTP 请求为 WebSocket 连接
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("升级失败:", err)
        return
    }
    defer conn.Close()

    // 处理客户端发送的消息
    for {
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            log.Println("读取消息失败:", err)
            break
        }

        // 打印收到的消息
        fmt.Printf("收到消息: %s\n", p)

        // 回应客户端的消息
        err = conn.WriteMessage(messageType, p)
        if err != nil {
            log.Println("写入消息失败:", err)
            break
        }
    }
}

func main() {
    http.HandleFunc("/ws", handler) // 定义 WebSocket 路由
    log.Println("服务器启动,监听端口 8080...")
    log.Fatal(http.ListenAndServe(":8080", nil)) // 启动 HTTP 服务器
}

代码解析:

  1. 我们使用 http.HandleFunc 来定义一个处理 /ws 路径的 WebSocket 请求。
  2. upgrader.Upgrade 将 HTTP 请求升级为 WebSocket 连接。
  3. conn.ReadMessage 用于读取客户端发送的消息,conn.WriteMessage 用于发送消息给客户端。
  4. 我们允许所有来源的连接,通过设置 CheckOrigintrue

3. 创建 WebSocket 客户端

WebSocket 客户端通过 websocket.Dial 函数连接到服务器,并与服务器进行双向通信。

WebSocket 客户端示例

package main

import (
    "fmt"
    "log"
    "github.com/gorilla/websocket"
)

func main() {
    // 连接到 WebSocket 服务器
    conn, _, err := websocket.DefaultDialer.Dial("ws://localhost:8080/ws", nil)
    if err != nil {
        log.Fatal("连接失败:", err)
    }
    defer conn.Close()

    // 向服务器发送消息
    message := []byte("Hello, WebSocket!")
    err = conn.WriteMessage(websocket.TextMessage, message)
    if err != nil {
        log.Fatal("发送消息失败:", err)
    }

    // 接收服务器的消息
    _, p, err := conn.ReadMessage()
    if err != nil {
        log.Fatal("读取消息失败:", err)
    }
    fmt.Printf("收到服务器的消息: %s\n", p)
}

代码解析:

  1. 使用 websocket.DefaultDialer.Dial 连接到 WebSocket 服务器。
  2. 发送消息通过 conn.WriteMessage,类型为 websocket.TextMessage
  3. 使用 conn.ReadMessage 来接收服务器的响应。

基础使用总结

  • WebSocket 客户端通过 Dial 方法连接到服务器。
  • 服务器端使用 Upgrader 升级 HTTP 请求为 WebSocket 连接。
  • 客户端和服务器端都可以使用 ReadMessageWriteMessage 进行双向通信。

进阶使用

1. 异常处理与连接管理

在 WebSocket 应用中,我们通常需要处理连接中断和异常情况。例如,客户端或服务器端可能会断开连接,我们需要相应地清理资源和重新连接。

进阶 WebSocket 服务器端示例

package main

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

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

func handler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("升级失败:", err)
        return
    }
    defer conn.Close()

    // 设置一个超时时间,连接 30 秒后关闭
    conn.SetReadDeadline(time.Now().Add(30 * time.Second))

    // 处理消息
    for {
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            log.Println("连接错误或超时:", err)
            break
        }
        fmt.Printf("收到消息: %s\n", p)

        err = conn.WriteMessage(messageType, p)
        if err != nil {
            log.Println("写入消息失败:", err)
            break
        }
    }
}

func main() {
    http.HandleFunc("/ws", handler)
    log.Println("服务器启动,监听端口 8080...")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

进阶部分:

  1. conn.SetReadDeadline 设置一个读取超时时间,如果在 30 秒内没有读取到消息,连接将被关闭。
  2. 当发生错误或连接断开时,我们会立即停止处理并释放连接资源。

2. 广播消息(群聊场景)

WebSocket 服务器可以通过广播将消息发送给所有连接的客户端。我们使用一个全局的连接池来管理每个连接。

广播服务器端示例

package main

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

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

var clients = make(map[*websocket.Conn]bool) // 连接池

func handler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("升级失败:", err)
        return
    }
    defer conn.Close()

    clients[conn] = true
    defer delete(clients, conn)

    for {
        _, message, err := conn.ReadMessage()
        if err != nil {
            log.Println("读取消息失败:", err)
            break
        }

        // 广播消息
        for client := range clients {
            if err := client.WriteMessage(websocket.TextMessage, message); err != nil {
                log.Println("发送广播消息失败:", err)
                client.Close()
                delete(clients, client)
            }
        }
    }
}

func main() {
    http.HandleFunc("/ws", handler)
    log.Println("服务器启动,监听端口 8080...")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

代码解析:

  1. clients 用来存储所有的 WebSocket 连接。
  2. 当收到消息时,服务器会广播给所有已连接的客户端。

总结

  • 客户端和服务器端的差异: 客户端通过 Dial 连接到 WebSocket 服务器,服务器端通过 http 升级 HTTP 请求为 WebSocket 连接。
  • 异常处理: WebSocket 连接可能会断开,需要及时处理。
  • 进阶功能: 例如广播功能,可以让服务器向所有连接的客户端发送消息。

通过这些基础和进阶示例,你可以使用 gorilla/websocket 来构建可靠的实时 WebSocket 应用。

每日更新-免费小火箭账号
不要错过任何机会,探索最新的应用和游戏,就在我们的平台。
立即访问
最后修改:2025 年 03 月 29 日
如果觉得我的文章对你有用,请随意赞赏