英文:
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's a connection pool
    connections map[*connection]bool
    ...
}
To broadcast message for all clients, we iterate over connection pool like this:
    case m := <-h.broadcast:
        for c := range h.connections {
            select {
            case c.send <- 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论