Websocket发送到特定客户端而不是广播

时间:2017-04-12 19:41:57

标签: go gorilla

我尝试修改大猩猩聊天示例,以便向特定客户端发送消息而不是广播。首先,我将特定客户端存储在集线器中,以反对它的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))
                    }
        }
}

客户端

我已向客户添加了一个字段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,指定&#39;到&#39;指示要发送的内容和要发送的消息。

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

1 个答案:

答案 0 :(得分:1)

定义代表消息的类型:

void sig_handler(int sig){
    if(sig == SIGINT){

        char res;
        printf("\nAre you sure you want to terminate (Y/N)?\n");
        kill(0, SIGTSTP); //envia sinal Stop ao processo pai

        do{
            read(STDIN_FILENO, &res, 1);
            if (res == 'Y' || res == 'y')
            {
                kill(0,SIGTERM); //envia sinal de Terminacao ao proceso pai
            }else
                if (res == 'N' || res == 'n')
                {
                    kill(0,SIGCONT); //envia sinal ao processo pai para continuar
                    break;
                }
        }while(res != 'Y' && res != 'y' && res != 'N' && res != 'n');
    }

}

struct sigaction oldsigaction; //declarar antes de subscribe_SIGINT

void subscribe_SIGINT(){
    sigaction(SIGTSTP, 0,&oldsigaction);
    struct sigaction newsigaction;
    newsigaction = oldsigaction;
    newsigaction.sa_handler = &sig_handler;
    sigaction(SIGTSTP, &newsigaction,0);
    signal(SIGINT, sig_handler);
}

向Hub添加字段:

type Message struct {
    id int
    data []byte
}

并初始化频道以及集线器的其他频道。

将以下案例添加到集线器的选择中:

Send chan Message

在客户端的接收循环中,解析JSON以获取id和消息数据并将其发送到集线器:

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