mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-03 22:45:13 +08:00
新增网络模块
This commit is contained in:
214
sysmodule/netmodule/kcpmodule/KcpModule.go
Normal file
214
sysmodule/netmodule/kcpmodule/KcpModule.go
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
package kcpmodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"github.com/xtaci/kcp-go/v5"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type KcpModule struct {
|
||||||
|
service.Module
|
||||||
|
blockCrypt kcp.BlockCrypt
|
||||||
|
|
||||||
|
mapClientLocker sync.RWMutex
|
||||||
|
mapClient map[string]*Client
|
||||||
|
process processor.IRawProcessor
|
||||||
|
|
||||||
|
kcpServer network.KCPServer
|
||||||
|
kcpCfg *network.KcpCfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
id string
|
||||||
|
kcpConn *network.NetConn
|
||||||
|
kcpModule *KcpModule
|
||||||
|
}
|
||||||
|
|
||||||
|
type KcpPackType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
KPTConnected KcpPackType = 0
|
||||||
|
KPTDisConnected KcpPackType = 1
|
||||||
|
KPTPack KcpPackType = 2
|
||||||
|
KPTUnknownPack KcpPackType = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type KcpPack struct {
|
||||||
|
Type KcpPackType //0表示连接 1表示断开 2表示数据
|
||||||
|
ClientId string
|
||||||
|
Data interface{}
|
||||||
|
RecyclerReaderBytes func(data []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) OnInit() error {
|
||||||
|
if km.kcpCfg == nil || km.process == nil {
|
||||||
|
return fmt.Errorf("please call the Init function correctly")
|
||||||
|
}
|
||||||
|
|
||||||
|
km.mapClient = make(map[string]*Client, km.kcpCfg.MaxConnNum)
|
||||||
|
km.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_Kcp, km.GetEventHandler(), km.kcpEventHandler)
|
||||||
|
km.process.SetByteOrder(km.kcpCfg.LittleEndian)
|
||||||
|
km.kcpServer.Init(km.kcpCfg)
|
||||||
|
km.kcpServer.NewAgent = km.NewAgent
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) Init(kcpCfg *network.KcpCfg, process processor.IRawProcessor) {
|
||||||
|
km.kcpCfg = kcpCfg
|
||||||
|
km.process = process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) Start() error {
|
||||||
|
return km.kcpServer.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) kcpEventHandler(ev event.IEvent) {
|
||||||
|
e := ev.(*event.Event)
|
||||||
|
switch KcpPackType(e.IntExt[0]) {
|
||||||
|
case KPTConnected:
|
||||||
|
km.process.ConnectedRoute(e.StringExt[0])
|
||||||
|
case KPTDisConnected:
|
||||||
|
km.process.DisConnectedRoute(e.StringExt[0])
|
||||||
|
case KPTUnknownPack:
|
||||||
|
km.process.UnknownMsgRoute(e.StringExt[0], e.Data, e.AnyExt[0].(func(data []byte)))
|
||||||
|
case KPTPack:
|
||||||
|
km.process.MsgRoute(e.StringExt[0], e.Data, e.AnyExt[0].(func(data []byte)))
|
||||||
|
}
|
||||||
|
|
||||||
|
event.DeleteEvent(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) SetBlob(blockCrypt kcp.BlockCrypt) {
|
||||||
|
km.blockCrypt = blockCrypt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) OnConnected(c *Client) {
|
||||||
|
ev := event.NewEvent()
|
||||||
|
ev.Type = event.Sys_Event_Kcp
|
||||||
|
ev.IntExt[0] = int64(KPTConnected)
|
||||||
|
ev.StringExt[0] = c.id
|
||||||
|
|
||||||
|
km.NotifyEvent(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) OnClose(c *Client) {
|
||||||
|
ev := event.NewEvent()
|
||||||
|
ev.Type = event.Sys_Event_Kcp
|
||||||
|
ev.IntExt[0] = int64(KPTDisConnected)
|
||||||
|
ev.StringExt[0] = c.id
|
||||||
|
|
||||||
|
km.NotifyEvent(ev)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) newClient(conn network.Conn) *Client {
|
||||||
|
km.mapClientLocker.Lock()
|
||||||
|
defer km.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
pClient := &Client{kcpConn: conn.(*network.NetConn), id: primitive.NewObjectID().Hex()}
|
||||||
|
pClient.kcpModule = km
|
||||||
|
km.mapClient[pClient.id] = pClient
|
||||||
|
|
||||||
|
return pClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) GetProcessor() processor.IRawProcessor {
|
||||||
|
return km.process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) SendRawMsg(clientId string, data []byte) error {
|
||||||
|
km.mapClientLocker.Lock()
|
||||||
|
client, ok := km.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
km.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
|
}
|
||||||
|
km.mapClientLocker.Unlock()
|
||||||
|
return client.kcpConn.WriteMsg(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) Close(clientId string) {
|
||||||
|
km.mapClientLocker.Lock()
|
||||||
|
client, ok := km.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
km.mapClientLocker.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
km.mapClientLocker.Unlock()
|
||||||
|
client.kcpConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) GetClientIp(clientId string) string {
|
||||||
|
km.mapClientLocker.Lock()
|
||||||
|
defer km.mapClientLocker.Unlock()
|
||||||
|
client, ok := km.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
removeAddr := client.kcpConn.RemoteAddr()
|
||||||
|
if removeAddr != nil {
|
||||||
|
return removeAddr.String()
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (km *KcpModule) NewAgent(conn network.Conn) network.Agent {
|
||||||
|
c := km.newClient(conn)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Run() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
log.Dump(string(buf[:l]), log.String("error", errString))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
c.kcpModule.OnConnected(c)
|
||||||
|
for c.kcpConn != nil {
|
||||||
|
c.kcpConn.SetReadDeadline(*c.kcpModule.kcpCfg.ReadDeadlineMill)
|
||||||
|
msgBuff, err := c.kcpConn.ReadMsg()
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("read client failed", log.ErrorAttr("error", err), log.String("clientId", c.id))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := c.kcpModule.process.Unmarshal(c.id, msgBuff)
|
||||||
|
if err != nil {
|
||||||
|
ev := event.NewEvent()
|
||||||
|
ev.Type = event.Sys_Event_Kcp
|
||||||
|
ev.IntExt[0] = int64(KPTUnknownPack)
|
||||||
|
ev.StringExt[0] = c.id
|
||||||
|
ev.Data = msgBuff
|
||||||
|
ev.AnyExt[0] = c.kcpConn.GetRecyclerReaderBytes()
|
||||||
|
c.kcpModule.NotifyEvent(ev)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ev := event.NewEvent()
|
||||||
|
ev.Type = event.Sys_Event_Kcp
|
||||||
|
ev.IntExt[0] = int64(KPTPack)
|
||||||
|
ev.StringExt[0] = c.id
|
||||||
|
ev.Data = data
|
||||||
|
ev.AnyExt[0] = c.kcpConn.GetRecyclerReaderBytes()
|
||||||
|
c.kcpModule.NotifyEvent(ev)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) OnClose() {
|
||||||
|
c.kcpModule.OnClose(c)
|
||||||
|
|
||||||
|
c.kcpModule.mapClientLocker.Lock()
|
||||||
|
delete(c.kcpModule.mapClient, c.id)
|
||||||
|
c.kcpModule.mapClientLocker.Unlock()
|
||||||
|
}
|
||||||
223
sysmodule/netmodule/tcpmodule/TcpModule.go
Normal file
223
sysmodule/netmodule/tcpmodule/TcpModule.go
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
package tcpmodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TcpModule struct {
|
||||||
|
tcpServer network.TCPServer
|
||||||
|
service.Module
|
||||||
|
|
||||||
|
mapClientLocker sync.RWMutex
|
||||||
|
mapClient map[string]*Client
|
||||||
|
process processor.IRawProcessor
|
||||||
|
tcpCfg *TcpCfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type TcpPackType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
TPTConnected TcpPackType = 0
|
||||||
|
TPTDisConnected TcpPackType = 1
|
||||||
|
TPTPack TcpPackType = 2
|
||||||
|
TPTUnknownPack TcpPackType = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type TcpPack struct {
|
||||||
|
Type TcpPackType //0表示连接 1表示断开 2表示数据
|
||||||
|
ClientId string
|
||||||
|
Data interface{}
|
||||||
|
RecyclerReaderBytes func(data []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
id string
|
||||||
|
tcpConn *network.NetConn
|
||||||
|
tcpModule *TcpModule
|
||||||
|
}
|
||||||
|
|
||||||
|
type TcpCfg struct {
|
||||||
|
ListenAddr string //监听地址
|
||||||
|
MaxConnNum int //最大连接数
|
||||||
|
PendingWriteNum int //写channel最大消息数量
|
||||||
|
LittleEndian bool //是否小端序
|
||||||
|
LenMsgLen int //消息头占用byte数量,只能是1byte,2byte,4byte。如果是4byte,意味着消息最大可以是math.MaxUint32(4GB)
|
||||||
|
MinMsgLen uint32 //最小消息长度
|
||||||
|
MaxMsgLen uint32 //最大消息长度,超过判定不合法,断开连接
|
||||||
|
ReadDeadlineSecond time.Duration //读超时
|
||||||
|
WriteDeadlineSecond time.Duration //写超时
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) OnInit() error {
|
||||||
|
if tm.tcpCfg == nil || tm.process == nil {
|
||||||
|
return fmt.Errorf("please call the Init function correctly")
|
||||||
|
}
|
||||||
|
|
||||||
|
//2.初始化网络模块
|
||||||
|
tm.tcpServer.Addr = tm.tcpCfg.ListenAddr
|
||||||
|
tm.tcpServer.MaxConnNum = tm.tcpCfg.MaxConnNum
|
||||||
|
tm.tcpServer.PendingWriteNum = tm.tcpCfg.PendingWriteNum
|
||||||
|
tm.tcpServer.LittleEndian = tm.tcpCfg.LittleEndian
|
||||||
|
tm.tcpServer.LenMsgLen = tm.tcpCfg.LenMsgLen
|
||||||
|
tm.tcpServer.MinMsgLen = tm.tcpCfg.MinMsgLen
|
||||||
|
tm.tcpServer.MaxMsgLen = tm.tcpCfg.MaxMsgLen
|
||||||
|
tm.tcpServer.ReadDeadline = tm.tcpCfg.ReadDeadlineSecond * time.Second
|
||||||
|
tm.tcpServer.WriteDeadline = tm.tcpCfg.WriteDeadlineSecond * time.Second
|
||||||
|
tm.mapClient = make(map[string]*Client, tm.tcpServer.MaxConnNum)
|
||||||
|
tm.tcpServer.NewAgent = tm.NewClient
|
||||||
|
|
||||||
|
//3.设置解析处理器
|
||||||
|
tm.process.SetByteOrder(tm.tcpCfg.LittleEndian)
|
||||||
|
|
||||||
|
//4.设置网络事件处理
|
||||||
|
tm.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_Tcp, tm.GetEventHandler(), tm.tcpEventHandler)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) Init(tcpCfg *TcpCfg, process processor.IRawProcessor) {
|
||||||
|
tm.tcpCfg = tcpCfg
|
||||||
|
tm.process = process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) Start() error {
|
||||||
|
return tm.tcpServer.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) tcpEventHandler(ev event.IEvent) {
|
||||||
|
pack := ev.(*event.Event).Data.(TcpPack)
|
||||||
|
switch pack.Type {
|
||||||
|
case TPTConnected:
|
||||||
|
tm.process.ConnectedRoute(pack.ClientId)
|
||||||
|
case TPTDisConnected:
|
||||||
|
tm.process.DisConnectedRoute(pack.ClientId)
|
||||||
|
case TPTUnknownPack:
|
||||||
|
tm.process.UnknownMsgRoute(pack.ClientId, pack.Data, pack.RecyclerReaderBytes)
|
||||||
|
case TPTPack:
|
||||||
|
tm.process.MsgRoute(pack.ClientId, pack.Data, pack.RecyclerReaderBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) NewClient(conn network.Conn) network.Agent {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
defer tm.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
clientId := primitive.NewObjectID().Hex()
|
||||||
|
pClient := &Client{tcpConn: conn.(*network.NetConn), id: clientId}
|
||||||
|
pClient.tcpModule = tm
|
||||||
|
tm.mapClient[clientId] = pClient
|
||||||
|
|
||||||
|
return pClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Client) GetId() string {
|
||||||
|
return slf.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Client) Run() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
buf := make([]byte, 4096)
|
||||||
|
l := runtime.Stack(buf, false)
|
||||||
|
errString := fmt.Sprint(r)
|
||||||
|
log.Dump(string(buf[:l]), log.String("error", errString))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTConnected}})
|
||||||
|
for slf.tcpConn != nil {
|
||||||
|
slf.tcpConn.SetReadDeadline(slf.tcpModule.tcpServer.ReadDeadline)
|
||||||
|
bytes, err := slf.tcpConn.ReadMsg()
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("read client failed", log.ErrorAttr("error", err), log.String("clientId", slf.id))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
data, err := slf.tcpModule.process.Unmarshal(slf.id, bytes)
|
||||||
|
if err != nil {
|
||||||
|
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTUnknownPack, Data: bytes, RecyclerReaderBytes: slf.tcpConn.GetRecyclerReaderBytes()}})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTPack, Data: data, RecyclerReaderBytes: slf.tcpConn.GetRecyclerReaderBytes()}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *Client) OnClose() {
|
||||||
|
slf.tcpModule.NotifyEvent(&event.Event{Type: event.Sys_Event_Tcp, Data: TcpPack{ClientId: slf.id, Type: TPTDisConnected}})
|
||||||
|
slf.tcpModule.mapClientLocker.Lock()
|
||||||
|
defer slf.tcpModule.mapClientLocker.Unlock()
|
||||||
|
delete(slf.tcpModule.mapClient, slf.GetId())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) SendMsg(clientId string, msg interface{}) error {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
client, ok := tm.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %d is disconnect!", clientId)
|
||||||
|
}
|
||||||
|
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
bytes, err := tm.process.Marshal(clientId, msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return client.tcpConn.WriteMsg(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) Close(clientId string) {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
defer tm.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
client, ok := tm.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if client.tcpConn != nil {
|
||||||
|
client.tcpConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
log.SWarning("close client:", clientId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) GetClientIp(clientId string) string {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
defer tm.mapClientLocker.Unlock()
|
||||||
|
pClient, ok := tm.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return pClient.tcpConn.GetRemoteIp()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) SendRawMsg(clientId string, msg []byte) error {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
client, ok := tm.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
|
}
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
return client.tcpConn.WriteMsg(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) GetConnNum() int {
|
||||||
|
tm.mapClientLocker.Lock()
|
||||||
|
connNum := len(tm.mapClient)
|
||||||
|
tm.mapClientLocker.Unlock()
|
||||||
|
return connNum
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tm *TcpModule) GetProcessor() processor.IRawProcessor {
|
||||||
|
return tm.process
|
||||||
|
}
|
||||||
200
sysmodule/netmodule/wsmodule/WSModule.go
Normal file
200
sysmodule/netmodule/wsmodule/WSModule.go
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
package wsmodule
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/duanhf2012/origin/v2/event"
|
||||||
|
"github.com/duanhf2012/origin/v2/log"
|
||||||
|
"github.com/duanhf2012/origin/v2/network"
|
||||||
|
"github.com/duanhf2012/origin/v2/network/processor"
|
||||||
|
"github.com/duanhf2012/origin/v2/service"
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WSModule struct {
|
||||||
|
service.Module
|
||||||
|
|
||||||
|
wsServer network.WSServer
|
||||||
|
|
||||||
|
mapClientLocker sync.RWMutex
|
||||||
|
mapClient map[string]*WSClient
|
||||||
|
process processor.IRawProcessor
|
||||||
|
wsCfg *WSCfg
|
||||||
|
}
|
||||||
|
|
||||||
|
type WSClient struct {
|
||||||
|
id string
|
||||||
|
wsConn *network.WSConn
|
||||||
|
wsModule *WSModule
|
||||||
|
}
|
||||||
|
|
||||||
|
type WSCfg struct {
|
||||||
|
ListenAddr string
|
||||||
|
MaxConnNum int
|
||||||
|
PendingWriteNum int
|
||||||
|
MaxMsgLen uint32
|
||||||
|
LittleEndian bool //是否小端序
|
||||||
|
}
|
||||||
|
|
||||||
|
type WSPackType int8
|
||||||
|
|
||||||
|
const (
|
||||||
|
WPTConnected WSPackType = 0
|
||||||
|
WPTDisConnected WSPackType = 1
|
||||||
|
WPTPack WSPackType = 2
|
||||||
|
WPTUnknownPack WSPackType = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type WSPack struct {
|
||||||
|
Type WSPackType //0表示连接 1表示断开 2表示数据
|
||||||
|
MsgProcessor processor.IRawProcessor
|
||||||
|
ClientId string
|
||||||
|
Data any
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) OnInit() error {
|
||||||
|
if ws.wsCfg == nil || ws.process == nil {
|
||||||
|
return fmt.Errorf("please call the Init function correctly")
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.wsServer.MaxConnNum = ws.wsCfg.MaxConnNum
|
||||||
|
ws.wsServer.PendingWriteNum = ws.wsCfg.PendingWriteNum
|
||||||
|
ws.wsServer.MaxMsgLen = ws.wsCfg.MaxMsgLen
|
||||||
|
ws.wsServer.Addr = ws.wsCfg.ListenAddr
|
||||||
|
|
||||||
|
//3.设置解析处理器
|
||||||
|
ws.process.SetByteOrder(ws.wsCfg.LittleEndian)
|
||||||
|
|
||||||
|
ws.mapClient = make(map[string]*WSClient, ws.wsServer.MaxConnNum)
|
||||||
|
ws.wsServer.NewAgent = ws.NewWSClient
|
||||||
|
|
||||||
|
//4.设置网络事件处理
|
||||||
|
ws.GetEventProcessor().RegEventReceiverFunc(event.Sys_Event_WebSocket, ws.GetEventHandler(), ws.wsEventHandler)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) Init(wsCfg *WSCfg, process processor.IRawProcessor) {
|
||||||
|
ws.wsCfg = wsCfg
|
||||||
|
ws.process = process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) Start() error {
|
||||||
|
ws.wsServer.Start()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) wsEventHandler(ev event.IEvent) {
|
||||||
|
pack := ev.(*event.Event).Data.(*WSPack)
|
||||||
|
switch pack.Type {
|
||||||
|
case WPTConnected:
|
||||||
|
ws.process.ConnectedRoute(pack.ClientId)
|
||||||
|
case WPTDisConnected:
|
||||||
|
ws.process.DisConnectedRoute(pack.ClientId)
|
||||||
|
case WPTUnknownPack:
|
||||||
|
ws.process.UnknownMsgRoute(pack.ClientId, pack.Data, ws.recyclerReaderBytes)
|
||||||
|
case WPTPack:
|
||||||
|
ws.process.MsgRoute(pack.ClientId, pack.Data, ws.recyclerReaderBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) recyclerReaderBytes(data []byte) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) NewWSClient(conn *network.WSConn) network.Agent {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
defer ws.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
pClient := &WSClient{wsConn: conn, id: primitive.NewObjectID().Hex()}
|
||||||
|
pClient.wsModule = ws
|
||||||
|
ws.mapClient[pClient.id] = pClient
|
||||||
|
|
||||||
|
return pClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *WSClient) GetId() string {
|
||||||
|
return wc.id
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *WSClient) Run() {
|
||||||
|
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTConnected}})
|
||||||
|
for {
|
||||||
|
bytes, err := wc.wsConn.ReadMsg()
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("read client is error", log.String("clientId", wc.id), log.ErrorAttr("err", err))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
data, err := wc.wsModule.process.Unmarshal(wc.id, bytes)
|
||||||
|
if err != nil {
|
||||||
|
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTUnknownPack, Data: bytes}})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTPack, Data: data}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wc *WSClient) OnClose() {
|
||||||
|
wc.wsModule.NotifyEvent(&event.Event{Type: event.Sys_Event_WebSocket, Data: &WSPack{ClientId: wc.id, Type: WPTDisConnected}})
|
||||||
|
wc.wsModule.mapClientLocker.Lock()
|
||||||
|
defer wc.wsModule.mapClientLocker.Unlock()
|
||||||
|
delete(wc.wsModule.mapClient, wc.GetId())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) GetProcessor() processor.IRawProcessor {
|
||||||
|
return ws.process
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) GetClientIp(clientId string) string {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
defer ws.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
pClient, ok := ws.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return pClient.wsConn.RemoteAddr().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) Close(clientId string) {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
defer ws.mapClientLocker.Unlock()
|
||||||
|
|
||||||
|
client, ok := ws.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if client.wsConn != nil {
|
||||||
|
client.wsConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) SendMsg(clientId string, msg interface{}) error {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
client, ok := ws.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
ws.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %s is disconnect!", clientId)
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.mapClientLocker.Unlock()
|
||||||
|
bytes, err := ws.process.Marshal(clientId, msg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return client.wsConn.WriteMsg(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *WSModule) SendRawMsg(clientId string, msg []byte) error {
|
||||||
|
ws.mapClientLocker.Lock()
|
||||||
|
client, ok := ws.mapClient[clientId]
|
||||||
|
if ok == false {
|
||||||
|
ws.mapClientLocker.Unlock()
|
||||||
|
return fmt.Errorf("client %s is disconnect", clientId)
|
||||||
|
}
|
||||||
|
ws.mapClientLocker.Unlock()
|
||||||
|
return client.wsConn.WriteMsg(msg)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user