Saya mempunyai apl beli-belah di mana pengguna boleh menyiarkan ketersediaan dan pengguna lain boleh mencarinya dan menambah ketersediaan mereka.
Saya kini mempunyai perkhidmatan sembang, pada asasnya untuk berbual. Iaitu, pelanggan boleh berbual dengan pembeli untuk mengesahkan butiran atau perkara lain. Sembang ini sepatutnya satu-satu. Jadi mungkin terdapat 5 pelanggan yang bertanya tentang siaran beli-belah dan saya mahu sembang itu unik kerana sembang pelanggan A tentang pembelian harus berasingan daripada sembang pelanggan B tentang pembelian yang sama. Pembeli sepatutnya dapat melihat sembang dan membalas.
Inilah yang saya miliki sekarang, tetapi ini nampaknya menyiarkan mesej kepada semua orang dalam rujukan. Saya hanya mahu pembeli-belah menerima mesej daripada pengirim tertentu tanpa orang lain mempunyai akses kepada sembang.
"client.go"
type client struct { conn *websocket.conn chatrepository chat.chatrepository message chan *message id string `json:"id"` reference string `json:"reference"` username string `json:"username"` sender string `json:"sender"` recipient string `json:"recipient"` } type message struct { content string `json:"content"` reference string `json:"reference"` // username string `json:"username"` sender string `json:"sender"` } func (c *client) writemessage() { defer func() { c.conn.close() }() for { message, ok := <-c.message if !ok { return } uuid, err := uuid.newv4() if err != nil { log.fatalf("failed to generate uuid: %v", err) } chatmessage := chat.chatmessage{ id: uuid.string(), sender: message.sender, // recipient: recipient, timestamp: time.now(), content: message.content, } if c.sender == message.sender { _, errx := c.chatrepository.addmessage(message.reference, chatmessage) if err != nil { log.fatalf("failed to generate uuid: %v", errx) } } c.conn.writejson(chatmessage) } } func (c *client) readmessage(hub *hub) { defer func() { hub.unregister <- c c.conn.close() }() for { _, m, err := c.conn.readmessage() if err != nil { if websocket.isunexpectedcloseerror(err, websocket.closegoingaway, websocket.closeabnormalclosure) { log.printf("error: %v", err) } break } msg := &message{ content: string(m), reference: c.reference, sender: c.sender, // username: c.username, } hub.broadcast <- msg } }
"hub.go"
type room struct { id string `json:"id"` name string `json:"name"` clients map[string]*client `json:"clients"` } type hub struct { rooms map[string]*room register chan *client unregister chan *client broadcast chan *message emmiter events.emitter } func newhub(emmiter events.emitter) *hub { return &hub{ rooms: make(map[string]*room), register: make(chan *client), unregister: make(chan *client), broadcast: make(chan *message, 5), emmiter: emmiter, } } func (h *hub) run() { for { select { case cl := <-h.register: if _, ok := h.rooms[cl.reference]; ok { r := h.rooms[cl.reference] if _, ok := r.clients[cl.id]; !ok { r.clients[cl.id] = cl } } case cl := <-h.unregister: if _, ok := h.rooms[cl.reference]; ok { if _, ok := h.rooms[cl.reference].clients[cl.id]; ok { // if len(h.rooms[cl.reference].clients) != 0 { // h.broadcast <- &message{ // content: "user left the chat", // reference: cl.reference, // username: cl.username, // } // } delete(h.rooms[cl.reference].clients, cl.id) close(cl.message) } } case m := <-h.broadcast: if _, ok := h.rooms[m.reference]; ok { for _, cl := range h.rooms[m.reference].clients { cl.message <- m if m.sender != cl.recipient { notifications.sendpush(h.emmiter, cl.recipient, fmt.sprintf("new message from %v", cl.username), m.content) } } } } } }
"pengendali.pergi"
type handler struct { hub *hub chatrepository chat.chatrepository } func newhandler(h *hub, chatrepository chat.chatrepository) *handler { return &handler{ hub: h, chatrepository: chatrepository, } } var upgrader = websocket.upgrader{ readbuffersize: 1024, writebuffersize: 1024, checkorigin: func(r *http.request) bool { return true }, } func (h *handler) joinroom(c *gin.context) { conn, err := upgrader.upgrade(c.writer, c.request, nil) if err != nil { utils.handleerror(c, nil, "error creating chat connection", http.statusbadgateway) return } reference := c.param("reference") sender := c.query("sender") username := c.query("username") recipient := c.query("recipient") if reference == "" || sender == "" || username == "" || recipient == "" { utils.handleerror(c, nil, "required parameters missing", http.statusbadgateway) return } if _, ok := h.hub.rooms[reference]; !ok { // room doesn't exist, handle accordingly _, err1 := h.chatrepository.getchathistory(reference) if err1 != nil { log.printf("failed to retrieve chat history: %s", err1) errx := h.chatrepository.createchat(reference) if errx != nil { utils.handleerror(c, nil, "error storing connection", http.statusbadgateway) return } } h.hub.rooms[reference] = &room{ id: reference, name: sender, clients: make(map[string]*client), } } cl := &client{ conn: conn, chatrepository: h.chatrepository, message: make(chan *message, 10), id: sender, reference: reference, sender: sender, username: username, recipient: recipient, } h.hub.register <- cl go cl.writemessage() cl.readmessage(h.hub) }
"route.go"
hub := ws.newhub(events.neweventemitter(conn)) wshandler := ws.newhandler(hub, pr.newchatrepository(db, client)) go hub.run() v1.get("/chat/ws/:reference", g.guard([]string{"user", "admin", "dispatcher"}, nil), wshandler.joinroom)
"chat.model.go" type Chat struct { ID string `json:"id,omitempty" bson:"_id,omitempty"` Reference string `json:"reference" bson:"reference"` Messages []ChatMessage `json:"messages" bson:"messages"` } type ChatMessage struct { ID string `json:"id,omitempty" bson:"_id,omitempty"` Sender string `json:"sender" bson:"sender,omitempty"` Timestamp time.Time `json:"timestamp" bson:"timestamp,omitempty"` Content string `json:"content" bson:"content,omitempty"` }
Sebab utama kod anda menyiarkan mesej kepada semua orang di dalam bilik dengan rujukan yang sama ialah anda melakukannya dalam kaedah hub
的 broadcast
频道中处理消息的方式。在当前的实现中,当发送消息时,它会被转发到同一房间中的每个客户端(即具有相同的引用)。这是在 hub
的 run
:
case m := <-h.broadcast: if _, ok := h.rooms[m.reference]; ok { for _, cl := range h.rooms[m.reference].clients { cl.message <- m ...
Saya harap skor 1-1. Sebut harga adalah postid
Jika reference
是 postid
, dan anda mahu komunikasi satu dengan satu antara pembeli (orang yang menghantar siaran ketersediaan) dan setiap pelanggan, maka anda perlu memastikan setiap sembang boleh dikenal pasti secara unik. p>
Kunci unik untuk setiap sesi sembang mestilah gabungan postid
(reference
) 和客户 id (sender
). Ini memastikan setiap pelanggan mempunyai sesi sembang unik dengan pembeli dalam setiap siaran.
Anda kemudian boleh mengemas kini gabungan client
结构,使其具有 chatid
,它是 reference
和 sender
.
type client struct { ... chatid string `json:"chat_id"` }
Anda boleh mengemas kini logo hub
来管理聊天会话地图(由 chatid
) dan bukannya bilik.
type hub struct { chats map[string]*chat ... }
Struktur setiap chat
adalah seperti berikut:
type chat struct { shopper *client customer *client }
Untuk mengendalikan mesej, apabila pelanggan menghantar mesej, mesej itu dihantar kepada pembeli, dan apabila pembeli membalas, mesej itu dihantar kepada pelanggan. Penghalaan boleh dilakukan menggunakan chatid
.
Sebagai contoh, dalam logik broadcast
anda:
case m := <-h.broadcast: chat, ok := h.chats[m.chatid] if ok { if m.sender == chat.customer.id { // message is from customer to shopper chat.shopper.message <- m } else if m.sender == chat.shopper.id { // message is from shopper to customer chat.customer.message <- m } }
*message
dan ia tidak mempunyai medan m
变量的类型为 *message
,它没有 chatid
.
Untuk menyelesaikan masalah ini, anda harus mempertimbangkan untuk menambah medan chatid
字段添加到 message
pada struktur
message
Pertama, kami mengubah suai struktur
type message struct { content string `json:"content"` chatid string `json:"chat_id"` sender string `json:"sender"` }
client
的 readmessage
方法中构造一个新的 message
Kemudian, apabila anda membina baharu dalam kaedah baca mesej
client
:
msg := &message{ content: string(m), chatid: c.chatid, sender: c.sender, }
chatID := reference + "_" + sender cl := &Client{ ... ChatID: chatID, } // If the chat session does not exist, create it. if _, ok := h.hub.Chats[chatID]; !ok { h.hub.Chats[chatID] = &Chat{ Customer: cl, Shopper: nil, // That will be set when the shopper joins. } } else { // That assumes only the customer or the shopper can join, not both at the same time. if h.hub.Chats[chatID].Shopper == nil { h.hub.Chats[chatID].Shopper = cl } else { h.hub.Chats[chatID].Customer = cl } }
Atas ialah kandungan terperinci Sembang satu lawan satu dengan soket golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!