2017-04-12 100 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(我忘記了確切的值)。如果通道填滿容量,那麼客戶端的發送循環可能會停留在對對等體的寫入中。最好放下客戶端然後停止集線器。 –

相關問題