@@ -2,6 +2,7 @@ package controller
22
33import (
44 "context"
5+ "encoding/json"
56 "errors"
67 "fmt"
78 "log"
@@ -1141,6 +1142,9 @@ func (cp *commonPage) ws(c *gin.Context) {
11411142 CheckOrigin : func (r * http.Request ) bool {
11421143 return true
11431144 },
1145+ // 添加缓冲区大小配置
1146+ ReadBufferSize : 1024 ,
1147+ WriteBufferSize : 1024 ,
11441148 }
11451149 conn , err := upgrader .Upgrade (c .Writer , c .Request , nil )
11461150 if err != nil {
@@ -1151,8 +1155,19 @@ func (cp *commonPage) ws(c *gin.Context) {
11511155 // 使用正确的构造函数
11521156 safeConn := websocketx .NewConn (conn )
11531157
1158+ // 设置连接参数
1159+ conn .SetReadDeadline (time .Now ().Add (60 * time .Second ))
1160+ conn .SetWriteDeadline (time .Now ().Add (10 * time .Second ))
1161+
1162+ // 设置ping/pong处理
1163+ conn .SetPongHandler (func (string ) error {
1164+ conn .SetReadDeadline (time .Now ().Add (60 * time .Second ))
1165+ return nil
1166+ })
1167+
11541168 // 使用一个channel来通知写入goroutine退出
11551169 done := make (chan struct {})
1170+ lastActivity := time .Now ()
11561171
11571172 // Read goroutine
11581173 go func () {
@@ -1161,35 +1176,76 @@ func (cp *commonPage) ws(c *gin.Context) {
11611176 safeConn .Close ()
11621177 }()
11631178 for {
1164- // 我们需要从连接中读取,以检测客户端是否已断开连接。
1165- // 我们不需要处理任何传入的消息。
1166- if _ , _ , err := safeConn .ReadMessage (); err != nil {
1179+ // 设置读取超时
1180+ conn .SetReadDeadline (time .Now ().Add (60 * time .Second ))
1181+
1182+ messageType , message , err := safeConn .ReadMessage ()
1183+ if err != nil {
11671184 if websocket .IsUnexpectedCloseError (err , websocket .CloseGoingAway , websocket .CloseAbnormalClosure ) {
11681185 log .Printf ("NG-ERROR: websocket read error: %v" , err )
11691186 }
11701187 break // 退出循环
11711188 }
1189+
1190+ // 更新活动时间
1191+ lastActivity = time .Now ()
1192+
1193+ // 处理客户端ping消息
1194+ if messageType == websocket .TextMessage {
1195+ var msg map [string ]interface {}
1196+ if err := json .Unmarshal (message , & msg ); err == nil {
1197+ if msgType , ok := msg ["type" ].(string ); ok && msgType == "ping" {
1198+ // 发送pong响应
1199+ pongMsg := map [string ]interface {}{"type" : "pong" , "timestamp" : time .Now ().Unix ()}
1200+ if pongData , err := json .Marshal (pongMsg ); err == nil {
1201+ safeConn .WriteMessage (websocket .TextMessage , pongData )
1202+ }
1203+ }
1204+ }
1205+ }
11721206 }
11731207 }()
11741208
11751209 // Write goroutine
11761210 go func () {
1177- ticker := time .NewTicker (time .Second * 1 ) // 从5秒改为1秒,提高更新频率
1178- defer ticker .Stop ()
1211+ ticker := time .NewTicker (time .Second * 1 ) // 1秒更新间隔,提供更好的实时性
1212+ pingTicker := time .NewTicker (time .Second * 30 ) // 30秒心跳间隔
1213+ defer func () {
1214+ ticker .Stop ()
1215+ pingTicker .Stop ()
1216+ }()
1217+
11791218 for {
11801219 select {
11811220 case <- done : // 从读取goroutine接收到退出信号
11821221 return
1222+ case <- pingTicker .C :
1223+ // 发送ping消息保持连接活跃
1224+ conn .SetWriteDeadline (time .Now ().Add (10 * time .Second ))
1225+ if err := safeConn .WriteMessage (websocket .PingMessage , []byte {}); err != nil {
1226+ log .Printf ("发送ping消息失败: %v" , err )
1227+ return
1228+ }
1229+
1230+ // 检查连接是否长时间无活动
1231+ if time .Since (lastActivity ) > 90 * time .Second {
1232+ log .Printf ("WebSocket连接长时间无活动,主动关闭" )
1233+ return
1234+ }
1235+
11831236 case <- ticker .C :
11841237 stat , err := cp .getServerStat (c , false )
11851238 if err != nil {
11861239 log .Printf ("NG-ERROR: failed to get server stat for websocket: %v" , err )
11871240 // 不要退出,让 done channel 处理终止
11881241 continue
11891242 }
1243+
1244+ // 设置写入超时
1245+ conn .SetWriteDeadline (time .Now ().Add (10 * time .Second ))
11901246 if err = safeConn .WriteMessage (websocket .TextMessage , stat ); err != nil {
11911247 // 写入失败,可能是因为连接已关闭。
1192- // 读取goroutine将处理清理工作。我们可以在这里退出。
1248+ log . Printf ( "WebSocket写入失败: %v" , err )
11931249 return
11941250 }
11951251 }
0 commit comments