Как обработать сообщение от правильного пользователя - PullRequest
1 голос
/ 28 мая 2020

Мой вариант использования:

  • Открыть 1-й веб-сокет (uuid = ec43898b-5e57-42f6-baee-09d5a212e22a)
  • Открыть 2-й веб-сокет (uuid = c266513f-ea45-43f6 -8ff5-693ed14719b3)
  • Отправить 1-е сообщение в 1-м веб-сокете, получить сообщение в 1-м веб-сокете (uuid = ec43898b-5e57-42f6-baee-09d5a212e22a)
  • Отправить 2-е сообщение во 2-м веб-сокете, но я получил сообщение в 1-й веб-сокет (uuid = ec43898b-5e57-42f6-baee-09d5a212e22a, НО мне нужно получить его по uuid = c266513f-ea45-43f6-8ff5-693ed14719b3 )

Но я получил все сообщения в первом WebSocket. Как разместить правильное сообщение на правильном веб-сайте?

Мои журналы:

2020/05/28 14:10:21 [HUB.register: new client: %!(EXTRA uuid.UUID=ec43898b-5e57-42f6-baee-09d5a212e22a, string=])
2020/05/28 14:10:22 [HUB.register: new client: %!(EXTRA uuid.UUID=c266513f-ea45-43f6-8ff5-693ed14719b3, string=])
2020/05/28 14:10:43 Got a message from client: %!(EXTRA uuid.UUID=ec43898b-5e57-42f6-baee-09d5a212e22a)
2020/05/28 14:10:52 Got a message from client: %!(EXTRA uuid.UUID=ec43898b-5e57-42f6-baee-09d5a212e22a)

Пример изображения, как это работает: screenshot1

Я использую пример по умолчанию с чатом для передачи сообщений:

клиент. go


// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
    uuid "github.com/satori/go.uuid"
    "log"
    "net/http"
    "time"

    "github.com/gorilla/websocket"
)

const (
    // Time allowed to write a message to the peer.
    writeWait = 10 * time.Second

    // Time allowed to read the next pong message from the peer.
    pongWait = 60 * time.Second

    // Send pings to peer with this period. Must be less than pongWait.
    pingPeriod = (pongWait * 9) / 10

    // Maximum message size allowed from peer.
    maxMessageSize = 512
)

var (
    newline = []byte{'\n'}
    space   = []byte{' '}
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

// Client is a middleman between the websocket connection and the hub.
type Client struct {
    id uuid.UUID

    hub *Hub

    // The websocket connection.
    conn *websocket.Conn

    // Buffered channel of outbound messages.
    send chan []byte
}

// readPump pumps messages from the websocket connection to the hub.
//
// The application runs readPump in a per-connection goroutine. The application
// ensures that there is at most one reader on a connection by executing all
// reads from this goroutine.
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, websocket.CloseAbnormalClosure) {
                log.Printf("error: %v", err)
            }
            break
        }

        log.Printf("Got a message from client: ",c.id)

        c.send <- message
        //_ = c.conn.WriteMessage(1, message)

        //message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
        //c.hub.broadcast <- message
    }
}

// writePump pumps messages from the hub to the websocket connection.
//
// A goroutine running writePump is started for each connection. The
// application ensures that there is at most one writer to a connection by
// executing all writes from this goroutine.
func (c *Client) writePump() {
    ticker := time.NewTicker(pingPeriod)
    defer func() {
        ticker.Stop()
        c.conn.Close()
    }()
    for {
        select {
        case message, ok := <-c.send:
            c.conn.SetWriteDeadline(time.Now().Add(writeWait))
            if !ok {
                // The hub closed the channel.
                c.conn.WriteMessage(websocket.CloseMessage, []byte{})
                return
            }

            w, err := c.conn.NextWriter(websocket.TextMessage)
            if err != nil {
                return
            }
            w.Write(message)

            // Add queued chat messages to the current websocket message.
            n := len(c.send)
            for i := 0; i < n; i++ {
                w.Write(newline)
                w.Write(<-c.send)
            }

            if err := w.Close(); err != nil {
                return
            }
        case <-ticker.C:
            c.conn.SetWriteDeadline(time.Now().Add(writeWait))
            if err := c.conn.WriteMessage(websocket.PingMessage, nil); err != nil {
                return
            }
        }
    }
}

// serveWs handles websocket requests from the peer.
func serveWs(hub *Hub, w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
        return
    }

    var newUuid, _ = uuid.NewV4()

    client := &Client{id: newUuid, hub: hub, conn: conn, send: make(chan []byte, 256)}
    client.hub.register <- client

    // Allow collection of memory referenced by the caller by doing all work in
    // new goroutines.
    go client.writePump()
    go client.readPump()
}

хаб. go:


// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import "log"

// Hub maintains the set of active clients and broadcasts messages to the
// clients.
type Hub struct {
    // Registered clients.
    clients map[*Client]bool

    // Inbound messages from the clients.
    broadcast chan []byte

    // Register requests from the clients.
    register chan *Client

    // Unregister requests from clients.
    unregister chan *Client
}

func newHub() *Hub {
    return &Hub{
        broadcast:  make(chan []byte),
        register:   make(chan *Client),
        unregister: make(chan *Client),
        clients:    make(map[*Client]bool),
    }
}

func (h *Hub) run() {
    for {
        select {
        case client := <-h.register:
            h.clients[client] = true
            log.Printf("[HUB.register: new client: ",client.id,"]")
        case client := <-h.unregister:
            if _, ok := h.clients[client]; ok {
                delete(h.clients, client)
                close(client.send)
            }
        case message := <-h.broadcast:
            for client := range h.clients {
                select {
                case client.send <- message:
                default:
                    close(client.send)
                    delete(h.clients, client)
                }
            }
        }
    }
}

...