Skip to content

websocket

在 Go 中使用 Gin 来实现 WebSocket 服务器非常常见,特别是当需要实时通信(如聊天应用、通知推送等)时。WebSocket 是一种全双工的通信协议,它使得客户端和服务器之间能够保持持久连接,允许双方在任何时间点都可以向对方发送数据。

Gin 本身不直接提供 WebSocket 功能,但你可以通过与 Go 的 WebSocket 库(如 gorilla/websocket)结合来实现 WebSocket 功能。

实现步骤:

  1. 安装 WebSocket 库 首先,你需要安装一个 WebSocket 的 Go 库。gorilla/websocket 是最常用的一个库。

    bash
    go get github.com/gorilla/websocket
  2. 创建 WebSocket 处理程序

    使用 gorilla/websocket 库可以很容易地在 Gin 中实现 WebSocket 连接。

示例:使用 Gin 和 WebSocket 进行通信

1. 创建一个简单的 WebSocket 服务器

go
package main

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

var upgrader = websocket.Upgrader{
	CheckOrigin: func(r *http.Request) bool {
		// 这里检查请求的来源,通常你会检查请求头中的 Origin 字段
		return true
	},
}

func handleWebSocket(c *gin.Context) {
	// 升级 HTTP 请求为 WebSocket 连接
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Println("Failed to upgrade to WebSocket:", err)
		return
	}
	defer conn.Close()

	log.Println("Client connected")

	// 持续监听 WebSocket 消息
	for {
		// 读取客户端发送的消息
		messageType, p, err := conn.ReadMessage()
		if err != nil {
			log.Println("Read message error:", err)
			break
		}

		// 打印客户端消息
		fmt.Printf("Received: %s\n", p)

		// 发送回客户端
		if err := conn.WriteMessage(messageType, p); err != nil {
			log.Println("Write message error:", err)
			break
		}
	}
}

func main() {
	r := gin.Default()

	// 设置 WebSocket 路由
	r.GET("/ws", handleWebSocket)

	// 启动服务器
	r.Run(":8080")
}

2. 前端使用 JavaScript 连接 WebSocket

在客户端,你可以通过浏览器使用 JavaScript 的 WebSocket API 来连接 Go WebSocket 服务器。

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>WebSocket Client</title>
</head>
<body>

  <h2>WebSocket Example</h2>
  <input type="text" id="messageInput" placeholder="Enter message" />
  <button id="sendButton">Send</button>

  <div id="response"></div>

  <script>
    const ws = new WebSocket("ws://localhost:8080/ws");

    ws.onopen = function(event) {
      console.log("WebSocket is open now.");
    };

    ws.onmessage = function(event) {
      // 接收到服务器发送的消息
      document.getElementById("response").innerText = "Received: " + event.data;
    };

    ws.onerror = function(error) {
      console.log("WebSocket Error: " + error);
    };

    ws.onclose = function(event) {
      console.log("WebSocket connection closed.");
    };

    // 发送消息到 WebSocket 服务器
    document.getElementById("sendButton").onclick = function() {
      const message = document.getElementById("messageInput").value;
      ws.send(message);
    };
  </script>
</body>
</html>

3. 解释代码

WebSocket 服务器端代码(Go + Gin):

  • upgraderwebsocket.Upgrader 负责将 HTTP 请求升级为 WebSocket 连接。它的 CheckOrigin 函数用于检查请求是否来自允许的源,通常用于防止跨站请求伪造(CSRF)攻击。
  • handleWebSocket:这是处理 WebSocket 连接的处理函数。它会在客户端连接时升级 HTTP 请求,并在连接后进入一个循环,读取客户端发送的消息,并返回给客户端相同的消息。
  • conn.ReadMessage:用于读取客户端发送的消息。根据 WebSocket 协议,服务器可以处理不同类型的消息(文本消息、二进制消息)。
  • conn.WriteMessage:用于将消息发送回客户端。

WebSocket 客户端代码(HTML + JavaScript):

  • new WebSocket():创建一个 WebSocket 连接,指向 Go 服务的 /ws 路由。
  • ws.onopen:WebSocket 连接打开时触发的事件。
  • ws.onmessage:接收到来自服务器的消息时触发的事件。
  • ws.send():通过 WebSocket 发送消息到服务器。

4. 启动应用并测试

  1. 运行 Go Gin 服务:

    bash
    go run main.go
  2. 在浏览器中打开客户端 HTML 文件,连接到 WebSocket 服务器。

  3. 在输入框中输入消息并点击发送,服务器会收到消息并将其返回,客户端会显示服务器返回的消息。

5. 高级用法

  • 广播消息:如果你想实现多用户的 WebSocket 广播消息(如多人聊天),可以维护一个连接池(map 或者 slice)来存储所有客户端连接,并通过迭代这个连接池来向所有连接发送消息。

  • 身份验证:可以在建立 WebSocket 连接之前,使用 HTTP 请求进行身份验证。在 WebSocket 连接升级之前检查请求头中的身份令牌。

  • 处理连接关闭和错误:在实际应用中,需要对连接关闭和错误进行处理,确保程序在异常发生时能够优雅地关闭连接。

6. 总结

  • 使用 Gin 作为 WebSocket 服务器非常简单,通过结合 gorilla/websocket 库,能够轻松地处理 WebSocket 连接、消息的发送和接收。
  • 前端可以通过 WebSocket API 与 Go WebSocket 服务进行实时的双向通信。
  • WebSocket 特别适合用于需要实时更新的应用,如即时聊天、实时数据推送等。