init
This commit is contained in:
119
Backend/internal/controller/websocket/ChatRoom.go
Normal file
119
Backend/internal/controller/websocket/ChatRoom.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type ChatMessage struct {
|
||||
RoomId string `json:"roomId"`
|
||||
UserId string `json:"userId"`
|
||||
Message string `json:"message"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}
|
||||
var clients = make(map[*websocket.Conn]bool)
|
||||
var roomClients = make(map[string]map[*websocket.Conn]bool)
|
||||
var broadcast = make(chan ChatMessage, 256)
|
||||
var mutex = sync.RWMutex{}
|
||||
var once sync.Once
|
||||
|
||||
func HandleChatConnections(r *ghttp.Request) {
|
||||
once.Do(func() {
|
||||
go handleBroadcast()
|
||||
})
|
||||
|
||||
ws, err := upgrader.Upgrade(r.Response.Writer, r.Request, nil)
|
||||
if err != nil {
|
||||
log.Printf("upgrade error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
mutex.Lock()
|
||||
clients[ws] = true
|
||||
mutex.Unlock()
|
||||
|
||||
defer func() {
|
||||
mutex.Lock()
|
||||
delete(clients, ws)
|
||||
for roomId, members := range roomClients {
|
||||
if _, ok := members[ws]; ok {
|
||||
delete(members, ws)
|
||||
if len(members) == 0 {
|
||||
delete(roomClients, roomId)
|
||||
}
|
||||
}
|
||||
}
|
||||
mutex.Unlock()
|
||||
ws.Close()
|
||||
}()
|
||||
|
||||
for {
|
||||
var msg ChatMessage
|
||||
err := ws.ReadJSON(&msg)
|
||||
if err != nil {
|
||||
log.Printf("read error: %v", err)
|
||||
break
|
||||
}
|
||||
|
||||
switch msg.Type {
|
||||
case "join":
|
||||
mutex.Lock()
|
||||
members, ok := roomClients[msg.RoomId]
|
||||
if !ok {
|
||||
members = make(map[*websocket.Conn]bool)
|
||||
roomClients[msg.RoomId] = members
|
||||
}
|
||||
members[ws] = true
|
||||
mutex.Unlock()
|
||||
case "leave":
|
||||
mutex.Lock()
|
||||
if members, ok := roomClients[msg.RoomId]; ok {
|
||||
delete(members, ws)
|
||||
if len(members) == 0 {
|
||||
delete(roomClients, msg.RoomId)
|
||||
}
|
||||
}
|
||||
mutex.Unlock()
|
||||
}
|
||||
|
||||
select {
|
||||
case broadcast <- msg:
|
||||
default:
|
||||
log.Printf("broadcast channel full, dropping message")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleBroadcast() {
|
||||
for {
|
||||
msg := <-broadcast
|
||||
mutex.RLock()
|
||||
members, ok := roomClients[msg.RoomId]
|
||||
if !ok {
|
||||
mutex.RUnlock()
|
||||
continue
|
||||
}
|
||||
for client := range members {
|
||||
err := client.WriteJSON(msg)
|
||||
if err != nil {
|
||||
log.Printf("write error: %v", err)
|
||||
client.Close()
|
||||
mutex.RUnlock()
|
||||
mutex.Lock()
|
||||
delete(members, client)
|
||||
if len(members) == 0 {
|
||||
delete(roomClients, msg.RoomId)
|
||||
}
|
||||
mutex.Unlock()
|
||||
mutex.RLock()
|
||||
}
|
||||
}
|
||||
mutex.RUnlock()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user