Golang WebSocket 心跳,细节决定成败

104 阅读3分钟

)

var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, }

func main() { http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Println(err) return }

	go heartbeat(conn)

	// 处理其他操作
})

log.Fatal(http.ListenAndServe(":8080", nil))

}

func heartbeat(conn *websocket.Conn) { ticker := time.NewTicker(5 * time.Second) defer ticker.Stop()

for {
	select {
	case <-ticker.C:
		err := conn.WriteMessage(websocket.PingMessage, []byte("heartbeat"))
		if err != nil {
			log.Println(err)
			return
		}
	}
}

}


在上面的代码中,我们使用`time.NewTicker`函数创建了一个定时器,每隔5秒触发一次。然后,我们使用`conn.WriteMessage`函数发送一个WebSocket ping消息作为心跳包。


#### 第三步:处理心跳响应


最后,我们需要处理来自客户端的心跳响应。如果客户端未在规定的时间内响应心跳包,我们可以将其标记为离线状态。以下是一个示例代码,用于处理心跳响应:



package main

import ( "log" "net/http" "time"

"github.com/gorilla/websocket"

)

var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, }

func main() { http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Println(err) return }

	go heartbeat(conn)

	// 处理其他操作
})

log.Fatal(http.ListenAndServe(":8080", nil))

}

func heartbeat(conn *websocket.Conn) { ticker := time.NewTicker(5 * time.Second) defer ticker.Stop()

for {
	select {
	case <-ticker.C:
		err := conn.WriteMessage(websocket.PingMessage, []byte("heartbeat"))
		if err != nil {
			log.Println(err)
			return
		}

		conn.SetReadDeadline(time.Now().Add(10 \* time.Second))
		\_, \_, err = conn.ReadMessage()
		if err != nil {
			log.Println("heartbeat response error:", err)
			return
		}
	}
}

}


在上述代码中,我们使用`conn.SetReadDeadline`函数设置一个10秒的读取超时时间。如果在超时时间内未收到心跳响应,将会触发`ReadMessage`函数返回错误。我们可以在错误处理程序中添加适当的操作,如重新连接或关闭连接。


### 案例


以下是三个使用Golang WebSocket心跳的案例:


#### 案例一:在线聊天应用


在一个在线聊天应用中,心跳机制可以用来检测用户的在线状态。当用户长时间没有发送消息时,服务器可以通过心跳机制检测到用户离线,并从在线用户列表中移除该用户。



func heartbeat(conn *websocket.Conn) { ticker := time.NewTicker(5 * time.Second) defer ticker.Stop()

for {
    select {
    case <-ticker.C:
        err := conn.WriteMessage(websocket.PingMessage, []byte("heartbeat"))
        if err != nil {
            // 处理错误
            return
        }

        conn.SetReadDeadline(time.Now().Add(10 \* time.Second))
        \_, \_, err = conn.ReadMessage()
        if err != nil {
            // 用户离线,从在线用户列表中移除
            return
        }
    }
}

}


#### 案例二:实时数据更新


在一个实时数据更新应用中,心跳机制可以用来检测客户端是否断开连接。当客户端长时间没有接收到心跳包时,服务器可以重新连接或采取其他措施,以确保数据的实时性。



func heartbeat(conn *websocket.Conn) { ticker := time.NewTicker(5 * time.Second) defer ticker.Stop()

for {
    select {
    case <-ticker.C:
        err := conn.WriteMessage(websocket.PingMessage, []byte("heartbeat"))
        if err != nil {
            // 处理错误
            return
        }

        conn.SetReadDeadline(time.Now().Add(10 \* time.Second))
        \_, \_, err = conn.ReadMessage()
        if err != nil {
            // 重新连接或其他操作
            return
        }
    }
}

}


#### 案例三:实时协作编辑工具


在一个实时协作编辑工具中,心跳机制可以用来检测用户的在线状态,并协调多个用户之间的编辑操作。当一个用户长时间没有发送心跳包时,服务器可以将其标记为离线状态,并将其编辑权限转移到其他在线用户上。



func heartbeat(conn *websocket.Conn) { ticker := time.NewTicker(5 * time.Second) defer ticker.Stop()

for {
    select {
    case <-ticker.C:
        err := conn.WriteMessage(websocket.PingMessage, []byte("heartbeat"))
        if err != nil {
            // 处理错误
            return
        }

        conn.SetReadDeadline(time.Now().Add(10 \* time.Second))
        \_, \_, err = conn.ReadMessage()
        if err != nil {
            // 标记用户离线,并将编辑权限转移给其他用户
            return
        }
    }
}

}


这些案例展示了在不同领域中使用Golang WebSocket心跳的可能性,但实际应用中还有更多情景可以使用心跳机制来提高系统的稳定性和性能。




![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/bc26e7f91f1148bfbc901dc222b3b1bd~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771250117&x-signature=K%2Fz%2B6jQNxtVFaZb42qQ4W3CqVlw%3D)
![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/dedc8076c96445abafb99916f1e63b87~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771250117&x-signature=8hpHMazffach3TwNCIirr5jsA8c%3D)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://gitee.com/vip204888)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**