【问题标题】:Sending a Websocket message to a specific channel in Go (using Gorilla)将 Websocket 消息发送到 Go 中的特定通道(使用 Gorilla)
【发布时间】:2020-01-07 01:54:44
【问题描述】:

我对 Go 非常陌生,并且发现自己使用套接字作为我的第一个项目。这是一个多余的问题,但我无法理解如何将 websocket 更新发送到 Go 中的特定通道(使用 Gorilla)。

我正在使用code sample from this link

这种方法。但未能修改以将消息发送到特定频道。

这是我的示例代码 ma​​in.go

func main() {
    flag.Parse()
    hub := newHub()
    go hub.run()
    http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println(hub)
        serveWs(hub, w, r)
    })
    err := http.ListenAndServe(*addr, nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

还有另外两个文件叫 hub.go 和 client.go 我认为hub.go到这里可以做点什么

return &Hub{
    broadcast:  make(chan []byte),
    register:   make(chan *Client),
    unregister: make(chan *Client),
    clients:    make(map[*Client]bool),
}

我应该从这里改变什么?

更新

我想要做的是我有一个用 go 编写的套接字服务器。 现在假设我们有许多客户端在服务器上使用特定的 URL(如 wss://abc.com/wss1 或者可能是 wss://abc.com/wss2

现在,如果客户端 wss1 向服务器发送消息,服务器将发出此消息,所有客户端都在监听 url wss1 而不是 wss2,反之亦然。

到目前为止,无论 wss1 还是 wss2,我都能够向所有客户端进行广播。 希望我说清楚了。

【问题讨论】:

  • 其实这不是重复的。我想发送所有正在收听特定频道的客户
  • 在更高层次上描述你想要做什么。例如,正在实施聊天室、一对一聊天还是其他?当您说频道时,您是指链接到的示例中的 Go 频道之一,还是指 Slack 中的聊天室或频道?
  • @CeriseLimón 我已经更新了我的问题。请看一下。任何帮助将不胜感激。

标签: go websocket gorilla


【解决方案1】:

要向 Gorilla 聊天示例添加“频道”或“聊天室”功能,请执行以下操作。我将在此答案中使用“房间”一词以避免与 Go 频道混淆。

为包含有效负载和房间标识符的消息定义类型:

type message struct {
   roomID string
   data []byte
}

将中心广播频道替换为:

broadcast chan message

向客户端类型添加房间标识符:

type Client struct {
    roomID string
    hub *Hub
    ...
}

处理程序从request URI 中提取房间标识符,并在创建Client 和发送message 时设置房间标识符。

Hubs clients 字段更改为以房间标识符为键的地图。初始化集线器时,根据需要初始化该字段。

// Registered clients by room
rooms map[string]map[*Client]bool

更改 Hub run 函数以使用房间。此代码在结构上与原始示例中的代码相似。

    select {
    case client := <-h.register:
        room := h.rooms[client.roomID]
        if room == nil {
           // First client in the room, create a new one
           room = make(map[*Client]bool)
           h.rooms[client.roomID] = room
        }
        room[client] = true
    case client := <-h.unregister:
        room := h.rooms[client.roomID]
        if room != nil {
            if _, ok := room[client]; ok {
                delete(room, client)
                close(client.send)
                if len(room) == 0 {
                   // This was last client in the room, delete the room
                   delete(h.rooms, client.roomID)
                }
            }
         }
    case message := <-h.broadcast:
        room := h.rooms[message.roomID]
        if room != nil {
            for client := range room {
                select {
                case client.send <- message.data:
                default:
                    close(client.send)
                    delete(room, client)
                }
            }
            if len(room) == 0 {
                // The room was emptied while broadcasting to the room.  Delete the room.
                delete(h.rooms, message.roomID)
            }
        }
    }

【讨论】:

  • 谢谢。我会尽力让你知道。
  • 这里出现错误。 room := h.rooms[message.roomID] error is message.roomID undefined (type []byte has no field or method roomID)
  • 好的。谢谢男人:)
  • 现在 hub.go 看起来不错。但是当我尝试从client.go运行时得到错误。这是 readPump 函数上的错误“不能使用消息(类型 [] 字节)作为发送中的类型消息”。你能再帮忙一次吗?
猜你喜欢
  • 2019-06-14
  • 2019-01-14
  • 2018-06-01
  • 2021-05-18
  • 1970-01-01
  • 1970-01-01
  • 2020-05-06
  • 2013-06-27
  • 1970-01-01
相关资源
最近更新 更多