发布于  更新于 

Gin操作WebSocket并开启SSL

1.前言

这段时间工作需求用到实现双工通信,因此选择WebSocket来开发,简单记录一下。

2.安装WebSocket

在 Go 语言中操作 WebSocket 可以通过使用 gorilla/websocket 包来实现。

1
go get github.com/gorilla/websocket

3.服务端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Upgrader 用于升级 HTTP 连接到 WebSocket 连接
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true // 允许所有来源的连接,生产环境应进行适当的来源验证
},
}

// WebSocketHandler 处理 WebSocket 连接
func WebSocketHandler(c *gin.Context) {
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
fmt.Println("Upgrade error:", err)
return
}
defer conn.Close()

for {
// 读取消息
messageType, message, err := conn.ReadMessage()
if err != nil {
fmt.Println("Read error:", err)
break
}

fmt.Printf("Received: %s\n", message)

// 回显消息
err = conn.WriteMessage(messageType, message)
if err != nil {
fmt.Println("Write error:", err)
break
}
}
}

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

// 配置 WebSocket 路由
router.GET("/ws", WebSocketHandler)

fmt.Println("Server started on :8080")
if err := router.Run(":8080"); err != nil {
fmt.Println("Run error:", err)
}
}

在 Upgrader 中还可以指定缓冲区的大小,修改如下:

1
2
3
4
5
6
7
var upgrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
return true
},
}

如果不使用gin使用原生http包开发的话,handler代码如下(主要是函数接收参数的变化):

1
2
3
4
func handler(w http.ResponseWriter, r *http.Request) {
conn, err := upgrader.Upgrade(w, r, nil)
// 同上
}

4.客户端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func main() {
u := url.URL{Scheme: "ws", Host: "localhost:8080", Path: "/ws"}
fmt.Printf("Connecting to %s\n", u.String())

conn, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
log.Fatal("Dial error:", err)
}
defer conn.Close()

// 发送消息
err = conn.WriteMessage(websocket.TextMessage, []byte("Hello, WebSocket!"))
if err != nil {
log.Fatal("Write error:", err)
}

// 读取消息
_, message, err := conn.ReadMessage()
if err != nil {
log.Fatal("Read error:", err)
}
fmt.Printf("Received: %s\n", message)
}

非必要,可以直接使用 postman 来快速模拟测试。

5.postman模拟测试

新建 request 选择 WebSocket 协议,接着 Connect 上,Send消息
语雀 2024-06-15 23.57.17.png

6.开启SSL

在 WebSocket 服务器中配置 SSL(即使用 wss 协议而不是 ws )

6.1生成测试用的自签名证书

1
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365

这会生成两个文件:key.pem(私钥)和 cert.pem(证书),放到项目的根目录即可。

6.2修改服务端代码

只要修改 router.Run(“:8080”) 为 router.RunTLS(“:8080”, “cert.pem”, “key.pem”)即可

1
2
3
4
5
6
7
8
9
10
11
12
func main() {
router := gin.Default()

// 配置 WebSocket 路由
router.GET("/ws", WebSocketHandler)

fmt.Println("Server started on :8080")
err := router.RunTLS(":8080", "cert.pem", "key.pem")
if err != nil {
fmt.Println("RunTLS error:", err)
}
}

6.3postman测试

只需将 localhost:8080/ws 修改为 wss://localhost:8080/ws 即可。