将 Websocket 消息发送到 Go 中的特定通道(使用 Gorilla)
Sending a Websocket message to a specific channel in Go (using Gorilla)
我是 Go 的新手,发现自己将使用套接字作为我的第一个项目。这是一个多余的问题,但我未能理解如何将 websocket 更新发送到 Go 中的特定通道(使用 Gorilla)。
我正在使用code sample from this link
这个方法。但是修改发送消息到特定频道失败。
这是我的示例代码
main.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 编写的套接字服务器。
现在假设我们有许多用 react 编写的客户端在服务器上监听特定的 url,比如 wss://abc.com/wss1 或者可能是 wss://abc.com/wss2
现在,如果客户端 wss1 向服务器发送消息,服务器将向所有侦听 url wss1 而不是 wss2 的客户端发出此消息,反之亦然。
到目前为止,我已经能够向所有客户端广播,无论是 wss1 还是 wss2。
希望我说清楚了。
要向 Gorilla 聊天示例添加 "channel" 或 "chat room" 功能,请执行以下操作。我将在此答案中使用 "room" 一词,以避免与 Go 频道混淆。
定义包含负载和房间标识符的消息类型:
type message struct {
roomID string
data []byte
}
将中心广播频道替换为:
broadcast chan message
为客户类型添加房间标识符:
type Client struct {
roomID string
hub *Hub
...
}
处理程序从 request URI 中提取房间标识符,并在创建 Client
和发送 message
时设置房间标识符。
将 Hub
s 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)
}
}
}
我是 Go 的新手,发现自己将使用套接字作为我的第一个项目。这是一个多余的问题,但我未能理解如何将 websocket 更新发送到 Go 中的特定通道(使用 Gorilla)。
我正在使用code sample from this link
这个方法。但是修改发送消息到特定频道失败。
这是我的示例代码 main.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 编写的套接字服务器。 现在假设我们有许多用 react 编写的客户端在服务器上监听特定的 url,比如 wss://abc.com/wss1 或者可能是 wss://abc.com/wss2
现在,如果客户端 wss1 向服务器发送消息,服务器将向所有侦听 url wss1 而不是 wss2 的客户端发出此消息,反之亦然。
到目前为止,我已经能够向所有客户端广播,无论是 wss1 还是 wss2。 希望我说清楚了。
要向 Gorilla 聊天示例添加 "channel" 或 "chat room" 功能,请执行以下操作。我将在此答案中使用 "room" 一词,以避免与 Go 频道混淆。
定义包含负载和房间标识符的消息类型:
type message struct {
roomID string
data []byte
}
将中心广播频道替换为:
broadcast chan message
为客户类型添加房间标识符:
type Client struct {
roomID string
hub *Hub
...
}
处理程序从 request URI 中提取房间标识符,并在创建 Client
和发送 message
时设置房间标识符。
将 Hub
s 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)
}
}
}