Reputation: 1938
I am very new to Go and have found myself working with sockets as my first project. This is a redundant question, but I have failed to understand how to send a websocket update to a specific channel in Go (using Gorilla).
I am using code sample from this link
this method. But failed to modify to send messages to specific channel.
Here is my sample code main.go
func main() {
flag.Parse()
hub := newHub()
go hub.run()
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
fmt.Println(hub)
serveWs(hub, w, r)
})
err := http.ListenAndServe(*addr, nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
There is other two files called hub.go and client.go I think hub.go below here something could be done
return &Hub{
broadcast: make(chan []byte),
register: make(chan *Client),
unregister: make(chan *Client),
clients: make(map[*Client]bool),
}
What should I change from here?
UPDATE
What I am trying to do is I have a socket server written in go. Now suppose we have many clients written in react listening on server with a specific url like wss://abc.com/wss1 or may be wss://abc.com/wss2
Now if client wss1 send a message to server, server will emit this message all clients listening on url wss1 not wss2 and vice versa.
Till now i have been able to do broadcast to all clients irrespective of wss1 or wss2. Hope I made it clear.
Upvotes: 3
Views: 5722
Reputation: 121199
To add a "channel" or "chat room" feature to the Gorilla chat example, do the following. I'll use the word "room" in this answer to avoid confusion with Go channels.
Define a type for messages that includes the payload and a room identifier:
type message struct {
roomID string
data []byte
}
Replace the hub broadcast channel with:
broadcast chan message
Add a room identifier to the Client type:
type Client struct {
roomID string
hub *Hub
...
}
The handler extracts the room identifier from the request URI and sets the room identifier when creating a Client
and sending a message
.
Change the Hub
s clients
fields to a map keyed by room identifier. Initialize this field as appropriate when initializing the hub.
// Registered clients by room
rooms map[string]map[*Client]bool
Change the Hub
run
function to work with rooms. This code is structurally similar to the code in the original example.
select {
case client := <-h.register:
room := h.rooms[client.roomID]
if room == nil {
// First client in the room, create a new one
room = make(map[*Client]bool)
h.rooms[client.roomID] = room
}
room[client] = true
case client := <-h.unregister:
room := h.rooms[client.roomID]
if room != nil {
if _, ok := room[client]; ok {
delete(room, client)
close(client.send)
if len(room) == 0 {
// This was last client in the room, delete the room
delete(h.rooms, client.roomID)
}
}
}
case message := <-h.broadcast:
room := h.rooms[message.roomID]
if room != nil {
for client := range room {
select {
case client.send <- message.data:
default:
close(client.send)
delete(room, client)
}
}
if len(room) == 0 {
// The room was emptied while broadcasting to the room. Delete the room.
delete(h.rooms, message.roomID)
}
}
}
Upvotes: 3