Golang WebSocket 心跳(1),2024年最新997页手淘Golang面试真题解析火爆全网

195 阅读3分钟
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
			}
		}
	}
}

在上面的代码中,我们使用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


![img](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/de8ea6b008ae42058c992e5ed836f33b~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771857264&x-signature=SIwrsmCIdd8ugSrwXL3bfi14eEU%3D)
![img](https://p3-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/9ae5b6c10c7745278783ec9dcdf2be91~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771857264&x-signature=0CL3z4jGUpnQWjkNZFA0GODexTs%3D)

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

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


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