英文:
Websocket send to specific client instead broadcast
问题
你想修改大猩猩聊天示例,使其能够向特定客户端发送消息,而不是广播给所有客户端。首先,你需要在Hub
结构体中存储特定客户端的ID。
Hub.go
type Hub struct {
Clients map[int]*Client // 将此部分修改为存储ID(int)
Broadcast chan []byte
Register chan *Client
Unregister chan *Client
}
func (h *Hub) Run() {
for {
select {
case client := <-h.Register:
fmt.Println("hub client register")
h.Clients[client.Id] = client
case client := <-h.Unregister:
fmt.Println("hub client Unregister")
fmt.Println(h.Clients[client.Id])
if h.Clients[client.Id] != nil {
delete(h.Clients, client.Id)
close(client.Send)
}
case message := <-h.Broadcast:
fmt.Println("to send to a specific client", string(message))
}
}
}
Client
我在Client
结构体中添加了一个Id
字段,用于标识发送消息的客户端。
type Client struct {
Hub *Hub
Conn *websocket.Conn
Send chan []byte
Id int // 客户端的ID
}
func (c *Client) readPump() {
defer func() {
c.Hub.Unregister <- c
c.Conn.Close()
}()
c.Conn.SetReadLimit(maxMessageSize)
c.Conn.SetReadDeadline(time.Now().Add(pongWait))
c.Conn.SetPongHandler(func(string) error { c.Conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
for {
_, message, err := c.Conn.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
log.Printf("error: %v", err)
}
break
}
message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
fmt.Println("client read message", string(message), "from", c.Id)
// {"to":512,"message":"Hi there."}
c.Hub.Broadcast <- message
}
}
接下来的步骤是什么,以便能够将消息发送给特定的客户端,而不是广播给所有客户端?
消息本身以JSON格式从客户端发送,其中指定了to
字段,表示要发送给谁以及要发送什么消息。
{"to":512,"message":"Hi there."}
英文:
I'm trying to modify the gorilla chat example to to send a message to a specific client instead of broadcast. First I'm storing the specific client in the hub against it's Id.
Hub.go
type Hub struct {
Clients map[int]*Client // Changed this piece to store id (int)
Broadcast chan []byte
Register chan *Client
Unregister chan *Client
}
func (h *Hub) Run() {
for {
select {
case client := <-h.Register:
fmt.Println("hub client register")
h.Clients[client.Id] = client
case client := <-h.Unregister:
fmt.Println("hub client Unregister")
fmt.Println(h.Clients[client.Id])
if h.Clients[client.Id] != nil {
delete(h.Clients, client.Id)
close(client.Send)
}
case message := <-h.Broadcast:
fmt.Println("to send to a specific client", string(message))
}
}
}
Client
I've added a field Id int to Client to know which client has sent a message
type Client struct {
Hub *Hub
Conn *websocket.Conn
Send chan []byte
Id int // Id of the client,
}
func (c *Client) readPump() {
defer func() {
c.Hub.Unregister <- c
c.Conn.Close()
}()
c.Conn.SetReadLimit(maxMessageSize)
c.Conn.SetReadDeadline(time.Now().Add(pongWait))
c.Conn.SetPongHandler(func(string) error { c.Conn.SetReadDeadline(time.Now().Add(pongWait)); return nil })
for {
_, message, err := c.Conn.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
log.Printf("error: %v", err)
}
break
}
message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
fmt.Println("client read message", string(message), "from", c.Id)
// {"to":512,"message":"Hi there."}
c.Hub.Broadcast <- message
}
}
What are the next steps to take to be able to send the message to a specific client instead of broadcasting.
the message itself is coming as JSON from the client specifying 'to' indicating who to send and what message to send.
{"to":512,"message":"Hi there."}
答案1
得分: 3
定义一个表示消息的类型:
type Message struct {
id int
data []byte
}
在 Hub 中添加一个字段:
Send chan Message
并在初始化通道时与 Hub 的其他通道一起初始化。
在 Hub 的 select 中添加以下 case:
case m := <-h.Send:
c, ok := clients[m.id]
if ok {
select {
case c.send <- m.data:
default:
delete(h.Clients, c.Id)
close(c.Send)
}
}
在客户端的接收循环中,解析 JSON 以获取 id 和消息数据,并将其发送到 Hub:
c.Hub.Send <- Message{id: id, data: data}
英文:
Define a type representing a message:
type Message struct {
id int
data []byte
}
Add a field to Hub:
Send chan Message
and initialize the channel along with the hub's other channels.
Add the following case to the hub's select:
case m := <-h.Send:
c, ok := clients[m.id]
if ok {
select {
case c.send <- m.data:
default:
delete(h.Clients, c.Id)
close(c.Send)
}
}
In the client's receive loop, parse the JSON to get the id and message data and send it to the hub:
c.Hub.Send <- Message{id: id, data: data}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论