You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
385 lines
8.9 KiB
385 lines
8.9 KiB
/**
|
|
* Created by GoLand.
|
|
* User: link1st
|
|
* Date: 2019-07-25
|
|
* Time: 16:24
|
|
*/
|
|
|
|
package websocket
|
|
|
|
import (
|
|
"fmt"
|
|
"gowebsocket/helper"
|
|
"gowebsocket/lib/cache"
|
|
"gowebsocket/models"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// 连接管理
|
|
type ClientManager struct {
|
|
Clients map[*Client]bool // 全部的连接
|
|
ClientsLock sync.RWMutex // 读写锁
|
|
Users map[string]*Client // 登录的用户 // appId+uuid
|
|
UserLock sync.RWMutex // 读写锁
|
|
Register chan *Client // 连接连接处理
|
|
Login chan *login // 用户登录处理
|
|
Unregister chan *Client // 断开连接处理程序
|
|
Broadcast chan []byte // 广播 向全部成员发送数据
|
|
}
|
|
|
|
func NewClientManager() (clientManager *ClientManager) {
|
|
clientManager = &ClientManager{
|
|
Clients: make(map[*Client]bool),
|
|
Users: make(map[string]*Client),
|
|
Register: make(chan *Client, 1000),
|
|
Login: make(chan *login, 1000),
|
|
Unregister: make(chan *Client, 1000),
|
|
Broadcast: make(chan []byte, 1000),
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 获取用户key
|
|
func GetUserKey(appId uint32, userId string) (key string) {
|
|
key = fmt.Sprintf("%d_%s", appId, userId)
|
|
|
|
return
|
|
}
|
|
|
|
/************************** manager ***************************************/
|
|
|
|
func (manager *ClientManager) InClient(client *Client) (ok bool) {
|
|
manager.ClientsLock.RLock()
|
|
defer manager.ClientsLock.RUnlock()
|
|
|
|
// 连接存在,在添加
|
|
_, ok = manager.Clients[client]
|
|
|
|
return
|
|
}
|
|
|
|
// GetClients
|
|
func (manager *ClientManager) GetClients() (clients map[*Client]bool) {
|
|
|
|
clients = make(map[*Client]bool)
|
|
|
|
manager.ClientsRange(func(client *Client, value bool) (result bool) {
|
|
clients[client] = value
|
|
|
|
return true
|
|
})
|
|
|
|
return
|
|
}
|
|
|
|
// 遍历
|
|
func (manager *ClientManager) ClientsRange(f func(client *Client, value bool) (result bool)) {
|
|
|
|
manager.ClientsLock.RLock()
|
|
defer manager.ClientsLock.RUnlock()
|
|
|
|
for key, value := range manager.Clients {
|
|
result := f(key, value)
|
|
if result == false {
|
|
return
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// GetClientsLen
|
|
func (manager *ClientManager) GetClientsLen() (clientsLen int) {
|
|
|
|
clientsLen = len(manager.Clients)
|
|
|
|
return
|
|
}
|
|
|
|
// 添加客户端
|
|
func (manager *ClientManager) AddClients(client *Client) {
|
|
manager.ClientsLock.Lock()
|
|
defer manager.ClientsLock.Unlock()
|
|
|
|
manager.Clients[client] = true
|
|
}
|
|
|
|
// 删除客户端
|
|
func (manager *ClientManager) DelClients(client *Client) {
|
|
manager.ClientsLock.Lock()
|
|
defer manager.ClientsLock.Unlock()
|
|
|
|
if _, ok := manager.Clients[client]; ok {
|
|
delete(manager.Clients, client)
|
|
}
|
|
}
|
|
|
|
// 获取用户的连接
|
|
func (manager *ClientManager) GetUserClient(appId uint32, userId string) (client *Client) {
|
|
|
|
manager.UserLock.RLock()
|
|
defer manager.UserLock.RUnlock()
|
|
|
|
userKey := GetUserKey(appId, userId)
|
|
if value, ok := manager.Users[userKey]; ok {
|
|
client = value
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// GetClientsLen
|
|
func (manager *ClientManager) GetUsersLen() (userLen int) {
|
|
userLen = len(manager.Users)
|
|
|
|
return
|
|
}
|
|
|
|
// 添加用户
|
|
func (manager *ClientManager) AddUsers(key string, client *Client) {
|
|
manager.UserLock.Lock()
|
|
defer manager.UserLock.Unlock()
|
|
|
|
manager.Users[key] = client
|
|
}
|
|
|
|
// 删除用户
|
|
func (manager *ClientManager) DelUsers(client *Client) (result bool) {
|
|
manager.UserLock.Lock()
|
|
defer manager.UserLock.Unlock()
|
|
|
|
key := GetUserKey(client.AppId, client.UserId)
|
|
if value, ok := manager.Users[key]; ok {
|
|
// 判断是否为相同的用户
|
|
if value.Addr != client.Addr {
|
|
|
|
return
|
|
}
|
|
delete(manager.Users, key)
|
|
result = true
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 获取用户的key
|
|
func (manager *ClientManager) GetUserKeys() (userKeys []string) {
|
|
|
|
userKeys = make([]string, 0)
|
|
manager.UserLock.RLock()
|
|
defer manager.UserLock.RUnlock()
|
|
for key := range manager.Users {
|
|
userKeys = append(userKeys, key)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 获取用户的key
|
|
func (manager *ClientManager) GetUserList(appId uint32) (userList []string) {
|
|
|
|
userList = make([]string, 0)
|
|
|
|
manager.UserLock.RLock()
|
|
defer manager.UserLock.RUnlock()
|
|
|
|
for _, v := range manager.Users {
|
|
if v.AppId == appId {
|
|
userList = append(userList, v.UserId)
|
|
}
|
|
}
|
|
|
|
fmt.Println("GetUserList len:", len(manager.Users))
|
|
|
|
return
|
|
}
|
|
|
|
// 获取用户的key
|
|
func (manager *ClientManager) GetUserClients() (clients []*Client) {
|
|
|
|
clients = make([]*Client, 0)
|
|
manager.UserLock.RLock()
|
|
defer manager.UserLock.RUnlock()
|
|
for _, v := range manager.Users {
|
|
clients = append(clients, v)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 向全部成员(除了自己)发送数据
|
|
func (manager *ClientManager) sendAll(message []byte, ignoreClient *Client) {
|
|
|
|
clients := manager.GetUserClients()
|
|
for _, conn := range clients {
|
|
if conn != ignoreClient {
|
|
conn.SendMsg(message)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 向全部成员(除了自己)发送数据
|
|
func (manager *ClientManager) sendAppIdAll(message []byte, appId uint32, ignoreClient *Client) {
|
|
|
|
clients := manager.GetUserClients()
|
|
for _, conn := range clients {
|
|
if conn != ignoreClient && conn.AppId == appId {
|
|
conn.SendMsg(message)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 用户建立连接事件
|
|
func (manager *ClientManager) EventRegister(client *Client) {
|
|
manager.AddClients(client)
|
|
|
|
fmt.Println("EventRegister 用户建立连接", client.Addr)
|
|
|
|
// client.Send <- []byte("连接成功")
|
|
}
|
|
|
|
// 用户登录
|
|
func (manager *ClientManager) EventLogin(login *login) {
|
|
|
|
client := login.Client
|
|
// 连接存在,在添加
|
|
if manager.InClient(client) {
|
|
userKey := login.GetKey()
|
|
manager.AddUsers(userKey, login.Client)
|
|
}
|
|
|
|
fmt.Println("EventLogin 用户登录", client.Addr, login.AppId, login.UserId)
|
|
|
|
orderId := helper.GetOrderIdTime()
|
|
SendUserMessageAll(login.AppId, login.UserId, orderId, models.MessageCmdEnter, "哈喽~")
|
|
}
|
|
|
|
// 用户断开连接
|
|
func (manager *ClientManager) EventUnregister(client *Client) {
|
|
manager.DelClients(client)
|
|
|
|
// 删除用户连接
|
|
deleteResult := manager.DelUsers(client)
|
|
if deleteResult == false {
|
|
// 不是当前连接的客户端
|
|
|
|
return
|
|
}
|
|
|
|
// 清除redis登录数据
|
|
userOnline, err := cache.GetUserOnlineInfo(client.GetKey())
|
|
if err == nil {
|
|
userOnline.LogOut()
|
|
cache.SetUserOnlineInfo(client.GetKey(), userOnline)
|
|
}
|
|
|
|
// 关闭 chan
|
|
// close(client.Send)
|
|
|
|
fmt.Println("EventUnregister 用户断开连接", client.Addr, client.AppId, client.UserId)
|
|
|
|
if client.UserId != "" {
|
|
orderId := helper.GetOrderIdTime()
|
|
SendUserMessageAll(client.AppId, client.UserId, orderId, models.MessageCmdExit, "用户已经离开~")
|
|
}
|
|
}
|
|
|
|
// 管道处理程序
|
|
func (manager *ClientManager) start() {
|
|
for {
|
|
select {
|
|
case conn := <-manager.Register:
|
|
// 建立连接事件
|
|
manager.EventRegister(conn)
|
|
|
|
case login := <-manager.Login:
|
|
// 用户登录
|
|
manager.EventLogin(login)
|
|
|
|
case conn := <-manager.Unregister:
|
|
// 断开连接事件
|
|
manager.EventUnregister(conn)
|
|
|
|
case message := <-manager.Broadcast:
|
|
// 广播事件
|
|
clients := manager.GetClients()
|
|
for conn := range clients {
|
|
select {
|
|
case conn.Send <- message:
|
|
default:
|
|
close(conn.Send)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************** manager info ***************************************/
|
|
// 获取管理者信息
|
|
func GetManagerInfo(isDebug string) (managerInfo map[string]interface{}) {
|
|
managerInfo = make(map[string]interface{})
|
|
|
|
managerInfo["clientsLen"] = clientManager.GetClientsLen() // 客户端连接数
|
|
managerInfo["usersLen"] = clientManager.GetUsersLen() // 登录用户数
|
|
managerInfo["chanRegisterLen"] = len(clientManager.Register) // 未处理连接事件数
|
|
managerInfo["chanLoginLen"] = len(clientManager.Login) // 未处理登录事件数
|
|
managerInfo["chanUnregisterLen"] = len(clientManager.Unregister) // 未处理退出登录事件数
|
|
managerInfo["chanBroadcastLen"] = len(clientManager.Broadcast) // 未处理广播事件数
|
|
|
|
if isDebug == "true" {
|
|
addrList := make([]string, 0)
|
|
clientManager.ClientsRange(func(client *Client, value bool) (result bool) {
|
|
addrList = append(addrList, client.Addr)
|
|
|
|
return true
|
|
})
|
|
|
|
users := clientManager.GetUserKeys()
|
|
|
|
managerInfo["clients"] = addrList // 客户端列表
|
|
managerInfo["users"] = users // 登录用户列表
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// 获取用户所在的连接
|
|
func GetUserClient(appId uint32, userId string) (client *Client) {
|
|
client = clientManager.GetUserClient(appId, userId)
|
|
|
|
return
|
|
}
|
|
|
|
// 定时清理超时连接
|
|
func ClearTimeoutConnections() {
|
|
currentTime := uint64(time.Now().Unix())
|
|
|
|
clients := clientManager.GetClients()
|
|
for client := range clients {
|
|
if client.IsHeartbeatTimeout(currentTime) {
|
|
fmt.Println("心跳时间超时 关闭连接", client.Addr, client.UserId, client.LoginTime, client.HeartbeatTime)
|
|
|
|
client.Socket.Close()
|
|
}
|
|
}
|
|
}
|
|
|
|
// 获取全部用户
|
|
func GetUserList(appId uint32) (userList []string) {
|
|
fmt.Println("获取全部用户", appId)
|
|
|
|
userList = clientManager.GetUserList(appId)
|
|
|
|
return
|
|
}
|
|
|
|
// 全员广播
|
|
func AllSendMessages(appId uint32, userId string, data string) {
|
|
fmt.Println("全员广播", appId, userId, data)
|
|
|
|
ignoreClient := clientManager.GetUserClient(appId, userId)
|
|
clientManager.sendAppIdAll([]byte(data), appId, ignoreClient)
|
|
}
|