WebSocket心跳机制通过定时收发Ping/Pong帧维持连接,防止因超时中断。服务端使用SetReadDeadline和SetPongHandler设置读取超时与Pong响应,并通过协程每30秒发送Ping;客户端设置SetPingHandler自动回复Pong,并在断连后每2秒重试。参数建议:心跳间隔30~45秒,读取超时60秒,重连采用指数退避。Gorilla WebSocket库可简洁实现上述逻辑,保障长连接稳定。

WebSocket连接在长时间无数据交互时容易因网络设备超时或服务器设置被中断。为保持连接活跃,需要实现心跳机制与断线重连逻辑。Golang中使用gorilla/websocket库可以轻松实现这一功能。
心跳机制通过定时发送小数据包(ping/pong)来告知对方连接仍有效。WebSocket协议原生支持控制帧Ping和Pong,服务端发送Ping,客户端需回应Pong,反之亦可。若在设定时间内未收到回应,则判定连接已断开。
服务端可通过SetReadDeadline设置读取超时,并监听客户端的Ping消息;同时用协程定期向客户端发送Ping帧以检测连接状态。
示例代码:
立即学习“go语言免费学习笔记(深入)”;
服务端设置心跳检测:
package main <p>import ( "log" "net/http" "time"</p><pre class="brush:php;toolbar:false;">"github.com/gorilla/websocket"
)
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.Print("Upgrade error:", err) return } defer conn.Close()
// 设置读取消息超时时间
conn.SetReadDeadline(time.Now().Add(60 * time.Second))
conn.SetPongHandler(func(string) error {
// 收到 Pong 后重置超时
conn.SetReadDeadline(time.Now().Add(60 * time.Second))
return nil
})
// 启动心跳发送协程
go func() {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if err := conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(5*time.Second)); err != nil {
log.Println("Ping error:", err)
return
}
}
}
}()
// 接收消息主循环
for {
messageType, p, err := conn.ReadMessage()
if err != nil {
log.Println("Read error:", err)
break
}
log.Printf("Received: %s", p)
if err := conn.WriteMessage(messageType, p); err != nil {
log.Println("Write error:", err)
break
}
}}
说明:
SetPongHandler用于处理客户端返回的Pong,收到后刷新读取超时。WriteControl发送Ping帧,避免阻塞正常消息通道。客户端同样需要监听服务端Ping并自动回复Pong,同时监测连接状态,在断开后尝试重连。
示例代码:
立即学习“go语言免费学习笔记(深入)”;
客户端心跳与重连逻辑:
package main <p>import ( "log" "time"</p><pre class="brush:php;toolbar:false;">"github.com/gorilla/websocket"
)
func connect(url string) *websocket.Conn { conn, _, err := websocket.DefaultDialer.Dial(url, nil) if err != nil { log.Println("Dial error:", err) return nil }
// 设置读取超时并处理 Ping
conn.SetReadDeadline(time.Now().Add(60 * time.Second))
conn.SetPingHandler(func(appData string) error {
log.Println("Received ping, replying pong")
conn.WriteControl(websocket.PongMessage, []byte(appData), time.Now().Add(time.Second))
return nil
})
return conn}
func startClient() { url := "ws://localhost:8080/ws" var conn *websocket.Conn
for {
if conn == nil {
conn = connect(url)
if conn == nil {
time.Sleep(2 * time.Second) // 重连间隔
continue
}
log.Println("Connected to server")
}
// 协程接收消息
done := make(chan struct{})
go func() {
defer close(done)
for {
_, msg, err := conn.ReadMessage()
if err != nil {
log.Println("Read error:", err)
conn.Close()
conn = nil
return
}
log.Printf("Recv: %s", msg)
}
}()
// 等待连接中断
select {
case <-done:
case <-time.After(30 * time.Second): // 防止无限阻塞
// 可选:主动发消息测试
}
// 开始重连
log.Println("Disconnected, reconnecting...")
time.Sleep(2 * time.Second)
}}
关键点:
SetPingHandler自动回复Pong,维持连接。done通道监控读取协程状态,判断是否断开。合理设置时间参数对稳定性至关重要:
基本上就这些。心跳加重连是保障长连接稳定的核心手段,Golang配合gorilla/websocket能简洁高效地实现。
以上就是Golang如何实现简单的WebSocket心跳机制_Golang WebSocket心跳与断线重连实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号