2017-04-12 163 views
1

我试图修改大猩猩聊天示例以发送消息到特定的客户端而不是广播。首先,我将特定客户端存储在集线器中,以防止它是Id。Websocket发送到特定的客户端,而不是广播

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)) 
        } 
     } 
} 

客户

我添加一个字段ID INT给客户知道哪些客户端发送一个消息

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 
     } 
} 

是什么接下来要发送消息到特定的客户端而不是广播。

消息本身即将来自客户端的JSON,指定'to'指示要发送的对象以及要发送的消息。

{"to":512,"message":"Hi there."} 

回答

0

定义表示消息类型:

type Message struct { 
    id int 
    data []byte 
} 

一个字段添加到集线器:

Send chan Message 

,并与所述轮毂的其他信道沿着初始化通道。

下列情况下加入到轮毂的选择:

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和消息数据并将其发送到集线器:

c.Hub.Send <- Message{id: id, data: data} 
+0

谢谢。我们是否需要违约条款?我在中心做了同样的事情,但未注册的处理程序。请指教。 – Developer

+0

如果您不添加默认子句,那么集线器可以阻止死客户端。原始示例中的客户端发送通道的容量大于1(我忘记了确切的值)。如果通道填满容量,那么客户端的发送循环可能会停留在对对等体的写入中。最好放下客户端然后停止集线器。 –

相关问题