如何保持 golang.org/x/net/websocket 的连接保持打开?

huangapple go评论73阅读模式
英文:

How to keep a golang.org/x/net/websocket open?

问题

我天真地使用[_, err := ws.Read(msg)](https://github.com/kaihendry/WebSocketHook/blob/master/server/main.go#L22)来保持我的代码中的一个 WebSocket 连接。我不认为它可靠地工作。

在其他代码中,我注意到人们使用了一个睡眠循环。保持 WebSocket 连接稳定的正确方法是什么?我假设底层库会进行 ping/pong 操作?

更新:我相当有信心认为[client.go](https://github.com/kaihendry/WebSocketHook/blob/fd3fc976bf1ce5865b48005e3d4024682a1c9533/client/client.go)有问题,因为它似乎在服务器上检测到断开连接后没有重新拨号。我制作了一个演示该问题的视频

英文:

I'm naively use _, err := ws.Read(msg) to keep a Web socket open in my code. I don't think it works reliably.

In other code I've noticed people doing a sleep loop. What's the correct way to keep a Web socket open & stable? I assume the underlying library does ping/pongs?

Update: I'm pretty confident that the client.go is to blame since it doesn't seem to redial after a disconnect is seen on the server. I made a video demonstrating the issue.

答案1

得分: 7

golang.org/x/net/websocket没有实现RFC 6455中的ping-pong功能,但是gorilla websocket实现了。以下是使用Gorilla websocket的最小示例:

c := time.Tick(pingInterval)
go func(){
    for _ := range c {
        if err := conn.WriteControl(Ping...); err != nil {
            // 处理错误
        }
    }
}()

-----

conn.SetPongHandler(func(string) error { return conn.SetReadDeadline(time.Now().Add(pingInterval)) })
go func(){
    for {
        if _, _, err := conn.NextReader(); err != nil {
            // 处理错误
        }
    }
}()
英文:

golang.org/x/net/websocket does not implement ping-pong from RFC 6455, but the gorilla websocket implementation does.
Minimal example with Gorilla websocket

c := time.Tick(pingInterval)
go func(){
       for  _ := range c {
           if err := conn.WriteControl(Ping...); err != nil {
                 handle error 
            }
      }
   }()

          -----

conn.SetPongHandler(func(string) error { return conn.SetReadDeadline(time.Now().Add(pingInterval)) })
go func(){
      for {
           if _, _, err := conn.NextReader(); err != nil {
                handle error
           }
       }
    }()

答案2

得分: 6

我误读了你的原始问题。

不,你正在以正确的方式进行操作。基本上,你需要阻止处理程序返回,以保持 WebSocket 连接保持活动状态。如果你不关心消息,只需丢弃它并不做任何处理即可。

人们通常会使用专用的 ReadWrite 协程来实现这一点,类似于以下方式:

func fishHandler(ws *websocket.Conn) {
    id := ws.RemoteAddr().String() + "-" + ws.Request().RemoteAddr + "-" + ws.Request().UserAgent()
    sockets[id] = ws

    go writePump(ws)
    readPump(ws)
}

func readPump(ws *websocket.Conn) {
    defer ws.Close()
    msg := make([]byte, 512)
    _, err := ws.Read(msg)
    if err != nil {
        return
    }
}

func writePump(ws *websocket.Conn) {
    // 在这里处理写入的消息
}

希望对你有所帮助!

英文:

I misread your original question.

No you're doing it the right away. You basically need to block the handler from returning to keep the websocket connection alive. If you don't care about the message, just discard it and do nothing with it.

A common way people do it is to have a dedicated Read and Write goroutine, something like:

func fishHandler(ws *websocket.Conn) {
	id := ws.RemoteAddr().String() + "-" + ws.Request().RemoteAddr + "-" + ws.Request().UserAgent()
	sockets[id] = ws

	go writePump(ws)
    readPump(ws)
}

func readPump(ws *websocket.Conn) {
    defer ws.Close()
    msg := make([]byte, 512)
    _, err := ws.Read(msg)
    if err != nil {
        return
    }
}

func writePump(ws *websocket.Conn) {
    // Hand the write messages here
}

huangapple
  • 本文由 发表于 2016年1月4日 20:23:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/34591094.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定