GO Websocket 向所有客户端发送消息

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

GO Websocket send all clients a message

问题

这段代码运行正常(为了更好的阅读,我对其进行了缩写)。

Client1向服务器发送请求时,服务器会立即回应。但是,其他客户端无法看到响应消息。

所以我想让它更进一步:当一个客户端向服务器发送请求时,服务器将回应所有客户端,以便所有客户端都能看到消息。

我该如何做到这一点?有没有适合初学者的示例或教程?

提前感谢!

服务器代码:

import (
        "github.com/gorilla/websocket"
       )

func main() {
    http.Handle("/server", websocket.Handler(echoHandler)) 
}

func echoHandler(ws *websocket.Conn) {
    conn, err := upgrader.Upgrade(w, r, nil) 
    if err != nil { 
      return
    }
    for {
      messageType, p, err := conn.ReadMessage() 
      if err != nil {
        return
      }

      print_binary(p) // 简单打印消息

      err = conn.WriteMessage(messageType, p);
      if err != nil {
        return
      }
    }
}
英文:

Everything works fine with this code (shortened it for better reading).

When Client1 sends a request to the Server, the Server responses to him instantly. But, the other clients can not see the response message.

So I want to make it go further: When a client sends a request to the server, the server will response to all clients so that all clients can see the message.

How can I do that? Any examples or nice tutorials for beginners?

Thanks in advance!

Server:

import (
        "github.com/gorilla/websocket"
       )

func main() {
    http.Handle("/server", websocket.Handler(echoHandler)) 
}

func echoHandler(ws *websocket.Conn) {
    conn, err := upgrader.Upgrade(w, r, nil) 
    if err != nil { 
      return
    }
    for {
      messageType, p, err := conn.ReadMessage() 
      if err != nil {
        return
      }

      print_binary(p) // simple print of the message

      err = conn.WriteMessage(messageType, p);
      if err != nil {
        return
      }
    }
}

答案1

得分: 10

你需要使用连接池来向所有连接广播消息。
你可以使用这个作为教程/示例:http://gary.burd.info/go-websocket-chat

简化一下:
连接池是一组已注册的连接,可以查看hub.connections

type connection struct {
    // WebSocket连接
    ws *websocket.Conn

    // 用于传输消息的缓冲通道
    send chan []byte

    // 连接所属的连接池
    h *hub
}

type hub struct {
    // 已注册的连接,即连接池
    connections map[*connection]bool

    ...
}

要向所有客户端广播消息,我们可以按照以下方式遍历连接池:

    case m := <-h.broadcast:
        for c := range h.connections {
            select {
            case c.send <- m:
            default:
                delete(h.connections, c)
                close(c.send)
            }
        }
    }

在这个示例中,h.broadcast 是一个包含需要广播的消息的通道。
我们使用select语句的default部分来删除具有满的或被阻塞的发送通道的连接。参考:https://stackoverflow.com/questions/32693931/what-is-the-benefit-of-sending-to-a-channel-by-using-select-in-go

英文:

You have to use connection pool to broadcast messages to all connections.
You can use that as tutorial/sample http://gary.burd.info/go-websocket-chat

Simplifying:
Connection pool is a collection of registered connections. See hub.connections:

type connection struct {
    // The websocket connection.
    ws *websocket.Conn

    // Buffered channel of outbound messages.
    send chan []byte

    // The hub.
    h *hub
}

type hub struct {
    // Registered connections. That&#39;s a connection pool
    connections map[*connection]bool

    ...
}

To broadcast message for all clients, we iterate over connection pool like this:

    case m := &lt;-h.broadcast:
        for c := range h.connections {
            select {
            case c.send &lt;- m:
            default:
                delete(h.connections, c)
                close(c.send)
            }
        }
    }

h.broadcast in that example is a channel with messages we need to broadcast.
We use default section of the select statement to delete connections with full or blocked send channels. See https://stackoverflow.com/questions/32693931/what-is-the-benefit-of-sending-to-a-channel-by-using-select-in-go

huangapple
  • 本文由 发表于 2015年7月21日 15:18:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/31532652.html
匿名

发表评论

匿名网友

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

确定