package wxcore import ( "encoding/json" "fmt" "strconv" "strings" "sync" "time" "xiawan/wx/srv/srvconfig" "xiawan/wx/srv/websrv" "xiawan/wx/clientsdk/baseinfo" "xiawan/wx/srv/wxface" ) // WXConnectMgr 微信链接管理器 type WXConnectMgr struct { canUseConnIDList []uint32 // 删掉/回收后的connID currentWxConnID uint32 wxConnectMap map[string]wxface.IWXConnect //管理的连接信息 wxConnLock sync.RWMutex //读写连接的读写锁 wxConnLockShowConnects sync.RWMutex //读写连接的读写锁 } // NewWXConnManager 创建一个WX链接管理 func NewWXConnManager() wxface.IWXConnectMgr { return &WXConnectMgr{ canUseConnIDList: make([]uint32, 0), currentWxConnID: 0, wxConnectMap: make(map[string]wxface.IWXConnect), } } // Add 添加链接 func (wm *WXConnectMgr) Add(wxConnect wxface.IWXConnect) { wm.wxConnLock.Lock() defer wm.wxConnLock.Unlock() // newConnID := uint32(0) // if len(wm.canUseConnIDList) > 0 { // newConnID = wm.canUseConnIDList[0] // wm.canUseConnIDList = wm.canUseConnIDList[1:] // } else { // newConnID = wm.currentWxConnID // wm.currentWxConnID++ // } newConnID := wm.currentWxConnID wm.currentWxConnID++ wxConnect.SetWXConnID(newConnID) wm.wxConnectMap[wxConnect.GetWXAccount().GetUserInfo().UUID] = wxConnect // 打印链接数量 wm.ShowConnectInfo() } // GetWXConnectByUserInfoUUID 根据UserInfoUUID获取微信链接 func (wm *WXConnectMgr) GetWXConnectByUserInfoUUID(userInfoUUID string) wxface.IWXConnect { wm.wxConnLock.Lock() defer wm.wxConnLock.Unlock() wxConn, ok := wm.wxConnectMap[userInfoUUID] if ok { fmt.Println(fmt.Sprintf("GET Connection locfree success by %s", userInfoUUID)) return wxConn } fmt.Println(fmt.Sprintf("GET Connection locfree Failed by %s abandon the conntection get !", userInfoUUID)) return nil } // GetWXConnectByWXID 根据WXID获取微信链接 func (wm *WXConnectMgr) GetWXConnectByWXID(wxid string) wxface.IWXConnect { for _, tryCoon := range wm.wxConnectMap { tmpUserInfo := tryCoon.GetWXAccount().GetUserInfo() if tmpUserInfo == nil || strings.Compare(tmpUserInfo.WxId, wxid) != 0 { continue } return tryCoon } //保护共享资源Map 加读锁 wm.wxConnLock.RLock() defer wm.wxConnLock.RUnlock() //根据WXID获取微信链接 for _, wxConn := range wm.wxConnectMap { tmpUserInfo := wxConn.GetWXAccount().GetUserInfo() if tmpUserInfo == nil || strings.Compare(tmpUserInfo.WxId, wxid) != 0 { continue } return wxConn } return nil } // Remove 删除连接 func (wm *WXConnectMgr) Remove(wxconn wxface.IWXConnect) { wm.wxConnLock.Lock() defer wm.wxConnLock.Unlock() // 在删除连接前,确保清理WebSocket连接 currentUserInfo := wxconn.GetWXAccount().GetUserInfo() if currentUserInfo != nil { currentTaskMgr := wxconn.GetWXTaskMgr() if taskMgr, ok := currentTaskMgr.(*WXTaskMgr); ok { wsTask := taskMgr.SocketMsgTask userUUID := currentUserInfo.UUID existingConn := wsTask.GetWebSocket(userUUID) if existingConn != nil { fmt.Println("Remove()时清理WebSocket连接:", userUUID) existingConn.Close() wsTask.DeleteWebSocket(userUUID) } // 禁用WebSocket功能 wsTask.SetWebSocketEnabled(false) } } //删除 delete(wm.wxConnectMap, currentUserInfo.UUID) //wm.canUseConnIDList = append(wm.canUseConnIDList, wxconn.GetWXConnID()) currentUserInfo = nil // 打印链接数量 wm.ShowConnectInfo() } // Len 获取当前连接 func (wm *WXConnectMgr) Len() int { return len(wm.wxConnectMap) } // ClearWXConn 删除并停止所有链接 func (wm *WXConnectMgr) ClearWXConn() { //保护共享资源Map 加写锁 wm.wxConnLock.Lock() defer wm.wxConnLock.Unlock() //停止并删除全部的连接信息 for uuid, wxConn := range wm.wxConnectMap { //停止 wxConn.Stop() //删除 delete(wm.wxConnectMap, uuid) } // 打印链接数量 wm.ShowConnectInfo() } // ShowConnectInfo 打印链接情况 func (wm *WXConnectMgr) ShowConnectInfo() string { wm.wxConnLockShowConnects.Lock() defer wm.wxConnLockShowConnects.Unlock() totalNum := wm.Len() noLoginNum := uint32(0) onlineNum := uint32(0) offlineNum := uint32(0) for _, wxConn := range wm.wxConnectMap { loginState := wxConn.GetWXAccount().GetLoginState() if loginState == baseinfo.MMLoginStateNoLogin { noLoginNum = noLoginNum + 1 } else if loginState == baseinfo.MMLoginStateOnLine { onlineNum = onlineNum + 1 } else if loginState == baseinfo.MMLoginStateOffLine { offlineNum = offlineNum + 1 } } showText := time.Now().Format("2006-01-02 15:04:05") showText = showText + " 总链接数量: " + strconv.Itoa(totalNum) + " 未登录数量:" + strconv.Itoa(int(noLoginNum)) showText = showText + " 在线数量: " + strconv.Itoa(int(onlineNum)) + " 离线数量: " + strconv.Itoa(int(offlineNum)) fmt.Println(showText) return showText } func (wm *WXConnectMgr) GetConnectInfo() map[string]interface{} { wm.wxConnLock.Lock() defer wm.wxConnLock.Unlock() totalNum := wm.Len() noLoginNum := int(0) onlineNum := int(0) offlineNum := int(0) var connections = make([]map[string]interface{}, 0) for _, wxConn := range wm.wxConnectMap { connections = append(connections, map[string]interface{}{ "loginState": wxConn.GetWXAccount().GetLoginState(), "userInfo": wxConn.GetWXAccount().GetUserInfo(), }) loginState := wxConn.GetWXAccount().GetLoginState() if loginState == baseinfo.MMLoginStateNoLogin { noLoginNum = noLoginNum + 1 } else if loginState == baseinfo.MMLoginStateOnLine { onlineNum = onlineNum + 1 } else if loginState == baseinfo.MMLoginStateOffLine { offlineNum = offlineNum + 1 } } return map[string]interface{}{ "time": time.Now().Format("2006-01-02 15:04:05"), "totalNum": totalNum, "noLoginNum": noLoginNum, "onlineNum": onlineNum, "offlineNum": offlineNum, "connections": connections, } } // 上报到后端 syncOnlineCount func updateOnlineCount(count int32) error { connectInfo := map[string]interface{}{} connectInfo["ip"] = srvconfig.GlobalSetting.TargetIp connectInfo["count"] = count // 将参数转换为 JSON 格式 paramBytes, err := json.Marshal(connectInfo) if err != nil { fmt.Println("Error marshaling JSON:", err) return err } if srvconfig.GlobalSetting.SyncOnlineCount == "" { return nil } // 发送 POST 请求 fmt.Printf("上报在线数量:%d\n", count) _, _ = websrv.TaskPostJson("http://"+srvconfig.GlobalSetting.SyncOnlineCount, paramBytes) return nil }