You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

442 lines
13 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package websocketservers
import (
"encoding/json"
"flx/Common"
"fmt"
"net"
"os"
"strings"
"sync"
"time"
"github.com/gorilla/websocket"
log "github.com/sirupsen/logrus"
)
var messageList [][]byte //储存因为不在线未发送的信息
var IsMaster bool = true
var MasterSendID []string = []string{"meetman", "electron"}
// ClientManager is a websocketservers manager
// 客户端管理
type ClientManager struct {
MuLock sync.RWMutex
//客户端 map 储存并管理所有的长连接client在线的为true不在的为false
Clients map[*Client]bool
//web端发送来的的message我们用broadcast来接收并最后分发给所有的client
Broadcast chan []byte
//新创建的长连接client
Register chan *Client
//新注销的长连接client
Unregister chan *Client
InvokeEventHandler func(uid string, ctype string, content string) //外部链接事件
InvokeEventHandlers func()
}
// Client is a websocketservers client
// 客户端 Client
type Client struct {
//用户id
Id string
//连接的socket
Socket *websocket.Conn
//发送的消息
Send chan []byte
}
var MClientID map[string]string
var FileData []map[string]interface{}
// Message is an object for websocketservers message which is mapped to json type
// 会把Message格式化成json
type Message struct {
//消息struct
ContentType string `json:"contenttype,omitempty"` //文本类型
Sender string `json:"sender,omitempty"` //发送者
Recipient string `json:"recipient,omitempty"` //接收者
Content interface{} `json:"datarecord,omitempty"` //内容
ContentTime string `json:"contenttime,omitempty"` //时间
}
// Manager define a ws server manager
// 创建客户端管理者
var Manager = ClientManager{
Broadcast: make(chan []byte),
Register: make(chan *Client),
Unregister: make(chan *Client),
Clients: make(map[*Client]bool),
}
func (manager *ClientManager) ManagerInit(invokeEventHandler func(uid string, ctype string, content string)) {
defer func() {
if r := recover(); r != nil {
log.Error("ManagerInit:", r)
}
}()
manager.InvokeEventHandler = invokeEventHandler
}
func (manager *ClientManager) ManagerInits(invokeEventHandler func()) {
defer func() {
if r := recover(); r != nil {
log.Error("ManagerInits:", r)
}
}()
manager.InvokeEventHandlers = invokeEventHandler
}
// Start is to start a ws server
func (manager *ClientManager) Start() {
defer func() {
if r := recover(); r != nil {
log.Error("websocketserversStart:", r)
}
}()
for {
select {
//如果有新的连接接入,就通过channel把连接传递给conn
case conn := <-manager.Register:
func() {
//把客户端的连接设置为true
manager.MuLock.Lock()
defer func() {
if err := recover(); err != nil {
fmt.Println("manager.MuLock:", err) // 打印错误信息
}
manager.MuLock.Unlock()
}()
manager.Clients[conn] = true
}()
//把返回连接成功的消息json格式化
// jsonMessage, _ := json.Marshal(&Message{ContentType: Common.WebSocketOpen, Content: "id:" + conn.Id + " has connected.", ContentTime: time.Now().Format("2006-01-02 15:04:05")})
tcpConn, ok := conn.Socket.UnderlyingConn().(*net.TCPConn)
if ok {
// log.Fatal("Failed to cast net.Conn to *net.TCPConn")
tcpConn.SetKeepAlive(true)
tcpConn.SetKeepAlivePeriod(3 * time.Second)
}
//调用客户端的send方法发送消息
// manager.Send(jsonMessage, conn)
if manager.InvokeEventHandler != nil {
manager.InvokeEventHandler(conn.Id, "Online", "")
// nethelper.ServerSendSeatDataChange(conn.Id, "Online") // 测试无纸化在线离线
}
//如果连接断开了
case conn := <-manager.Unregister:
//判断连接的状态如果是true,就关闭send删除连接client的值
if _, ok := manager.Clients[conn]; ok {
if manager.InvokeEventHandler != nil {
manager.InvokeEventHandler(conn.Id, "Offline", "")
// nethelper.ServerSendSeatDataChange(conn.Id, "Offline") // 测试无纸化在线离线
}
close(conn.Send)
func() {
//把客户端的连接设置为true
manager.MuLock.Lock()
defer func() {
if err := recover(); err != nil {
fmt.Println("manager.MuLock:", err) // 打印错误信息
}
manager.MuLock.Unlock()
}()
delete(manager.Clients, conn)
}()
// jsonMessage, _ := json.Marshal(&Message{ContentType: Common.WebSocketClose, Content: "id:" + conn.Id + " has disconnected.", ContentTime: time.Now().Format("2006-01-02 15:04:05")})
// manager.Send(jsonMessage, conn)
}
//广播
case message := <-manager.Broadcast:
//遍历已经连接的客户端,把消息发送给他们
fmt.Println("33333333333-------")
func() {
//把客户端的连接设置为true
manager.MuLock.Lock()
defer func() {
if err := recover(); err != nil {
fmt.Println("manager.MuLock:", err) // 打印错误信息
}
manager.MuLock.Unlock()
}()
for conn := range manager.Clients {
select {
case conn.Send <- message:
default:
close(conn.Send)
delete(manager.Clients, conn)
}
}
}()
fmt.Println("333333333333333333333")
}
}
}
// Send is to send ws message to ws client
// 定义客户端管理的send方法,屏蔽不需要发送的客户
func (manager *ClientManager) Send(message []byte, ignore *Client) {
defer func() {
if r := recover(); r != nil {
log.Error("WebSocketserverSend:", r)
// 可以在这里处理错误,比如设置 tempresultmap 之类的
}
}()
// fmt.Println("444444444----------")
manager.MuLock.RLock()
defer func() {
if err := recover(); err != nil {
fmt.Println("manager.MuLock:", err) // 打印错误信息
}
manager.MuLock.RUnlock()
}()
//只遍历键时,使用下面的形式:
for conn := range manager.Clients {
//不给屏蔽的连接发送消息
if conn != ignore {
conn.Send <- message
}
}
// fmt.Println("4444444444444444")
}
// 定义客户端管理的send方法,屏蔽不需要发送的客户
func (manager *ClientManager) SendMessageByClientId(message []byte, uid string) {
// fmt.Println("555555555555555-----------")
manager.MuLock.RLock()
defer func() {
if err := recover(); err != nil {
fmt.Println("manager.MuLock:", err) // 打印错误信息
log.Error("SendMessageByClientId:", err)
}
manager.MuLock.RUnlock()
// fmt.Println("55555555555555555")
}()
//只遍历键时,使用下面的形式:
for conn := range manager.Clients {
//发给指定用户的连接发送消息
if conn.Id == uid {
// // 打印消息发送前的日志,记录目标 IP 和 UID
// fmt.Printf("Sending message to client with UID: %s, IP: %s\n", uid, "打印消息发送前的日志")
// // 发送消息
// select {
// case conn.Send <- message:
// // 成功发送
// fmt.Println("Message sent successfully成功发送.")
// default:
// // 发送失败,管道阻塞
// fmt.Println("Failed to send message: Channel is blocked or client is not responsive发送失败管道阻塞.")
// }
// // 发送后,确认已发送的消息
// fmt.Printf("发送后确认已发送的消息Message sent to %s: %s\n", uid, string(message))
conn.Send <- message
}
}
}
// 定义客户端管理的send方法,屏蔽不需要发送的客户
func (manager *ClientManager) SendMessageByClientType(message []byte, uid string) {
defer func() {
if err := recover(); err != nil {
fmt.Println("manager.MuLock:", err) // 打印错误信息
log.Error("SendMessageByClientType:", err)
}
manager.MuLock.RUnlock()
// fmt.Println("55555555555555555")
}()
// fmt.Println("6666666666----------")
manager.MuLock.RLock()
//只遍历键时,使用下面的形式:
for conn := range manager.Clients {
//发给指定用户的连接发送消息
if strings.Contains(conn.Id, uid) {
conn.Send <- message
}
}
// fmt.Println("666666666666666666666")
}
// 定义客户端结构体的read方法
func (c *Client) Read() {
defer func() {
//触发关闭
Manager.Unregister <- c
c.Socket.Close()
if err := recover(); err != nil {
log.WithFields(log.Fields{
"function": "Read",
"error": err,
}).Error("Read")
log.Error("websocketserversRead:", err)
// log.Printf("OpenDevice: %v", err) // 记录错误信息到日志
fmt.Println("Read:", err) // 打印错误信息
}
}()
for {
// c.Socket.SetReadDeadline(time.Now().Add(10 * time.Second)) // 设置读取超时为10秒
//读取消息
_, message, err := c.Socket.ReadMessage()
//如果有错误信息,就注销这个连接然后关闭
if err != nil {
Manager.Unregister <- c
c.Socket.Close()
break
}
//如果没有错误信息就把信息放入broadcast
// var jsonMessage []byte
// if message != nil && string(message) == Common.WebSocketHeartBeat {
// jsonMessage, _ = json.Marshal(&Message{ContentType: Common.WebSocketHeartBeat, Sender: c.Id, Content: string(message), ContentTime: time.Now().Format("2006-01-02 15:04:05")})
// } else {
// jsonMessage, _ = json.Marshal(&Message{ContentType: Common.WebSocketBroadCast, Sender: c.Id, Content: string(message), ContentTime: time.Now().Format("2006-01-02 15:04:05")})
// }
tempMap := make(map[string]interface{})
json.Unmarshal(message, &tempMap)
if tempMap["ContentType"] == Common.WebSocketChat {
jsonMessage, _ := json.Marshal(&Message{ContentType: Common.WebSocketChat, Sender: c.Id, Recipient: tempMap["Recipient"].(string), Content: tempMap["Content"].(string), ContentTime: time.Now().Format("2006-01-02 15:04:05")})
//Content 有要发送给谁
//发给李四
fmt.Println("77777777777----------")
func() {
//把客户端的连接设置为true
Manager.MuLock.RLock()
defer func() {
if err := recover(); err != nil {
fmt.Println("Manager.MuLock:", err) // 打印错误信息
}
Manager.MuLock.RUnlock()
}()
for k, v := range Manager.Clients {
if k.Id == tempMap["Recipient"].(string) {
for true {
if v == true {
messageList = append(messageList, jsonMessage)
for _, m := range messageList {
k.Send <- m
}
break
}
}
}
}
}()
fmt.Println("777777777777777777777")
} else if tempMap["ContentType"] == Common.WebSocketRefresh {
onlineList := make([]string, 0)
fmt.Println("88888888888888----------")
func() {
//把客户端的连接设置为true
Manager.MuLock.RLock()
defer func() {
if err := recover(); err != nil {
fmt.Println("Manager.MuLock:", err) // 打印错误信息
}
Manager.MuLock.RUnlock()
}()
for k, v := range Manager.Clients {
cli := k
if v {
onlineList = append(onlineList, cli.Id)
}
jsonMessage, _ := json.Marshal(&Message{ContentType: Common.WebSocketRefresh, Sender: c.Id, Content: onlineList, ContentTime: time.Now().Format("2006-01-02 15:04:05")})
c.Send <- jsonMessage
}
}()
fmt.Println("888888888888888888888888")
} else if tempMap["ContentType"] == Common.WebSocketCloseExe {
//浏览器关闭时调用退出会议
// localcache.DisposeContent()
// ServerSendElectronScreenClose()
if Manager.InvokeEventHandlers != nil {
Manager.InvokeEventHandlers()
}
time.Sleep(time.Second * 2)
os.Exit(0)
} else if tempMap["ContentType"] == Common.WebSocketCloseElectron {
//浏览器关闭时调用退出会议
// localcache.DisposeContent()
ServerSendElectronScreenClose()
if Manager.InvokeEventHandlers != nil {
Manager.InvokeEventHandlers()
}
} else if tempMap["ContentType"] == Common.WebSocketFileRate {
FileData = append(FileData, tempMap)
}
// log.Println(string(jsonMessage))
//触发消息发送
//Manager.Broadcast <- jsonMessage
}
}
func (c *Client) Write() {
defer func() {
c.Socket.Close()
if err := recover(); err != nil {
log.WithFields(log.Fields{
"function": "Write",
"error": err,
}).Error("Write")
log.Error("websocketserversWrite:", err)
// log.Printf("OpenDevice: %v", err) // 记录错误信息到日志
fmt.Println("Write:", err) // 打印错误信息
}
}()
for {
select {
//从send里读消息
case message, ok := <-c.Send:
//如果没有消息
if !ok {
c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
fmt.Println("发送信息错误")
return
}
//有消息就写入发送给web端
// log.Println(string(message))
if IsMaster {
c.Socket.WriteMessage(websocket.TextMessage, message)
//fmt.Println("发送信息111", MasterSendID, string(message))
} else {
for i := 0; i < len(MasterSendID); i++ {
if MasterSendID[i] == c.Id {
c.Socket.WriteMessage(websocket.TextMessage, message)
//fmt.Println("发送信息222", MasterSendID, string(message))
break
}
}
}
// c.Socket.WriteMessage(websocket.TextMessage, message)
}
}
}