2024年5月29日18:05:44

master
zm 2024-05-29 18:05:56 +08:00
commit d6bacf3452
18 changed files with 1083 additions and 0 deletions

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module zinx
go 1.20

92
utils/globalobj.go Normal file
View File

@ -0,0 +1,92 @@
package utils
import (
"encoding/json"
"fmt"
"os"
"zinx/ziface"
)
/**
zinx , 使
zinx.json
*/
type GlobalObj struct {
/**
Server
*/
TcpServer ziface.IServer //当前zinx 全局的server 对象
Host string //当前服务器监听的ip
TcpPort int //当前服务器监听的端口
Name string //当前服务的名称
/**
zinx
*/
Version string //当前zinx 的版本号
MaxConn int //当前服务器允许的最大连接数
MaxPackageSize uint32 //当前zinx 框架数据包的最大值
WokePoolSize uint32 //当前业务工作worker 池的goroutine 数量
MaxWorkerTaskLen uint32 // zinx 框架最多允许用户开辟多少个worker (限定条件)
}
/*
GlobalObject globalobj
*/
var GlobalObject *GlobalObj
/*
init, GlobalObject
*/
func init() {
//默认配置
GlobalObject = &GlobalObj{
Name: "ZinxServer",
Host: "0.0.0.0",
Version: "V0.4",
TcpPort: 8999,
MaxConn: 1000,
MaxPackageSize: 4096,
WokePoolSize: 10,
MaxWorkerTaskLen: 1024,
}
//尝试从配置文件加载 config/zinx.json
GlobalObject.Reload()
}
/*
Reload config/zinx.json
*/
func (g *GlobalObj) Reload() {
data, err := os.ReadFile("conf/zinx.json")
if err != nil {
fmt.Println("conf/zinx.json 读取错误!")
panic(err)
}
err = json.Unmarshal(data, &GlobalObject)
if err != nil {
fmt.Println("conf/zinx.json 解析错误!")
panic(err)
}
// 打开 JSON 文件
//file, err := os.Open("conf/zinx.json")
//if err != nil {
// fmt.Println(err)
// return
//}
//defer file.Close()
//// 解码 JSON 数据
//decoder := json.NewDecoder(file)
//err = decoder.Decode(&GlobalObject)
//if err != nil {
// fmt.Println(err)
// return
//}
//fmt.Println(GlobalObject)
}

22
ziface/iconnManager.go Normal file
View File

@ -0,0 +1,22 @@
package ziface
/*
IConnManager
*/
type IConnManager interface {
//添加连接
Add(conn IConnection)
//删除连接
Remove(conn IConnection)
//根据connID 获取连接
Get(connID uint32) (IConnection, error)
//得到当前的连接总数
Len() int
//清楚或终止所有连接
ClearConn()
}

37
ziface/iconnection.go Normal file
View File

@ -0,0 +1,37 @@
package ziface
import "net"
// IConnection 定义链接的抽象层
type IConnection interface {
// Start 启动链接
Start()
// Stop 关闭连接
Stop()
// GetTcpConnection 获取当前链接绑定的socket
GetTcpConnection() *net.TCPConn
// GetConnectionID 获取当前链接模块的ID
GetConnectionID() uint32
// RemoteAddr 获取远程客户点的tcp 状态 ip port
RemoteAddr() net.Addr
// SendMsg 发送数据,将数据发送给远程客户端
SendMsg(msgId uint32, data []byte) error
//设置连接属性
SetProperty(key string, value interface{})
//获取连接属性
GetProperty(key string) (interface{}, error)
//移除连接属性
RemoveProperty(key string)
}
// 定义一个处理链接的方法
type HandleFunc func(*net.TCPConn, []byte, int) error

18
ziface/idatapack.go Normal file
View File

@ -0,0 +1,18 @@
package ziface
/*
IDataPack
,
tcp,tcp
*/
type IDataPack interface {
//获取包的头长度方法
GetHeadLen() uint32
//封包方法
Pack(msg IMessage) ([]byte, error)
//拆包方法
UnPack([]byte) (IMessage, error)
}

22
ziface/imessage.go Normal file
View File

@ -0,0 +1,22 @@
package ziface
/*
*
message ,
*/
type IMessage interface {
//获取消息的id
GetMsgId() uint32
//获取消息的长度
GetDataLen() uint32
//获取消息的内容
GetData() []byte
//设置消息的id
SetMsgId(uint32)
//设置消息的长度
SetDataLen(uint32)
//设置消息的内容
SetData([]byte)
}

22
ziface/imessageHandler.go Normal file
View File

@ -0,0 +1,22 @@
package ziface
/*
*
*/
type IMsgHandler interface {
//调度/执行队形router 消息处理方法
DoMsgHandler(request IRequest)
//为消息添加具体的处理模块
AddRouter(msgId uint32, router IRouter)
//启动work 工作池
StartWorkPool()
//启动一个worker 工作流程
//StartOneWorker(workerId int, taskQueue chan IRequest)
SendMsgTaskQueue(request IRequest)
}

16
ziface/irequest.go Normal file
View File

@ -0,0 +1,16 @@
package ziface
/**
*/
type IRequest interface {
//获取连接
GetConnection() IConnection
//请求的消息数据
GetData() []byte
//获取请求消息的id
GetMsgId() uint32
}

17
ziface/irouter.go Normal file
View File

@ -0,0 +1,17 @@
package ziface
/**
IRequest
*/
type IRouter interface {
//在处理conn 业务之前的钩子方法 hook
PreHandle(request IRequest)
//在处理conn 业务的主方法hook
Handle(request IRequest)
//在处理conn业务之后的钩子方法
PostHandle(request IRequest)
}

32
ziface/iserver.go Normal file
View File

@ -0,0 +1,32 @@
package ziface
// 定义一个服务器接口
type IServer interface {
//启动服务器
Start()
//停止服务器
Stop()
//运行服务器
Serve()
//路由功能:给当前服务注册一个路由业务方法,供客户端链接处理使用
AddRouter(msgId uint32, router IRouter)
//获取当前server 的连接管理器
GetConnMgr() IConnManager
//注册OnConnStat 钩子函数方法
SetOnConnStart(func(connection IConnection))
//注册OnConnStop 钩子函数方法
SetOnConnStop(func(connection IConnection))
//调用OnConnStat 钩子函数方法
CallOnConnStart(connection IConnection)
//调用OnConnStop 钩子函数方法
CallOnConnStop(connection IConnection)
}

87
znet/connManager.go Normal file
View File

@ -0,0 +1,87 @@
package znet
import (
"errors"
"fmt"
"sync"
"zinx/ziface"
)
/*
*/
type ConnManager struct {
//管理的连接集合
connections map[uint32]ziface.IConnection
//保护连接集合的读写锁
connLock sync.RWMutex
}
// NewConnManager 创建当前连接的方法
func NewConnManager() *ConnManager {
return &ConnManager{
connections: make(map[uint32]ziface.IConnection),
}
}
// Add 添加连接
func (connMgr *ConnManager) Add(conn ziface.IConnection) {
//保护共享资源map ,加写锁
connMgr.connLock.Lock()
defer connMgr.connLock.Unlock()
//将conn 加入到connmanager 中
connMgr.connections[conn.GetConnectionID()] = conn
fmt.Println("connID = ", conn.GetConnectionID(), "add connection add to connmanager successfully : conn num = ", connMgr.Len())
}
// Remove 删除连接
func (connMgr *ConnManager) Remove(conn ziface.IConnection) {
//保护共享资源map ,加写锁
connMgr.connLock.Lock()
defer connMgr.connLock.Unlock()
//删除链接
delete(connMgr.connections, conn.GetConnectionID())
fmt.Println("connID = ", conn.GetConnectionID(), "delete connection from connmanager successfully : conn num = ", connMgr.Len())
}
// 根据connID 获取连接
func (connMgr *ConnManager) Get(connID uint32) (ziface.IConnection, error) {
//保护共享资源map ,加写锁
connMgr.connLock.RLock()
defer connMgr.connLock.RUnlock()
if conn, ok := connMgr.connections[connID]; ok {
//找到了
return conn, nil
} else {
return nil, errors.New("connection is not found ")
}
}
// 得到当前的连接总数
func (connMgr *ConnManager) Len() int {
return len(connMgr.connections)
}
// 清楚或终止所有连接
func (connMgr *ConnManager) ClearConn() {
//保护共享资源map ,加写锁
connMgr.connLock.Lock()
defer connMgr.connLock.Unlock()
//删除conn 饼停止conn 的工作
for connID, conn := range connMgr.connections {
//停止
conn.Stop()
//删除
delete(connMgr.connections, connID)
}
fmt.Println("clear all connection successfully ! conn num = ", connMgr.Len())
}

260
znet/connection.go Normal file
View File

@ -0,0 +1,260 @@
package znet
import (
"errors"
"fmt"
"io"
"net"
"sync"
"zinx/utils"
"zinx/ziface"
)
// Connection 链接模块
type Connection struct {
//当前连接隶属于那个server
TcpServer ziface.IServer
//当前链接的socket tcp 套接字
Conn *net.TCPConn
//链接的id
ConnID uint32
//当前链接的状态
isClosed bool
////当前链接锁绑定的处理业务的api
//handleApi ziface.HandleFunc
//告知当前链接的退出/停止 (由reading 告诉 writering 退出)
ExitChan chan bool
//无缓冲的管道,用于读写goroutine之间的 消息通信
msgChan chan []byte
//消息处理的msgId 处理业务对应的api
MsgHandler ziface.IMsgHandler
//连接属性集合
property map[string]interface{}
//保护连接属性的锁
propertyLock sync.RWMutex
}
// NewConnection 初始化链接
func NewConnection(server ziface.IServer, conn *net.TCPConn, connID uint32, handler ziface.IMsgHandler) *Connection {
c := &Connection{
TcpServer: server,
Conn: conn,
ConnID: connID,
isClosed: false,
MsgHandler: handler,
msgChan: make(chan []byte),
ExitChan: make(chan bool, 1),
property: make(map[string]interface{}),
}
//将conn 加入到 connManager 中
c.TcpServer.GetConnMgr().Add(c)
return c
}
func (c *Connection) StartReader() {
fmt.Println("reading goroutine is running ...")
defer fmt.Println("connID = ", c.ConnID, " reading is exit , remote addr is =", c.Conn.RemoteAddr().String())
defer c.Stop()
for {
//读取数据
//buf := make([]byte, utils.GlobalObject.MaxPackageSize)
//
//_, err := c.Conn.Read(buf)
//if err != nil {
// fmt.Println("conn read err")
// continue
//}
//创建一个拆包解包对象
dp := NewDataPack()
//读取客户端的8个字节
headData := make([]byte, dp.GetHeadLen())
//拆包得到msgId 和 msgDataLen
if _, err := io.ReadFull(c.GetTcpConnection(), headData); err != nil {
fmt.Println("read msg head error", err)
break
}
msg, err := dp.UnPack(headData)
if err != nil {
fmt.Println("UnPack error", err)
break
}
var data []byte
if msg.GetDataLen() > 0 {
data = make([]byte, msg.GetDataLen())
if _, err := io.ReadFull(c.GetTcpConnection(), data); err != nil {
fmt.Println("read msg data error", err)
}
}
msg.SetData(data)
//调用链接处理的api
//if err = c.handleApi(c.Conn, buf, len); err != nil {
// fmt.Println("connID = ", c.ConnID, "handle is err = ", err)
//}
//的到当前conn 数据的request 请求数据
req := Request{
conn: c,
msg: msg,
}
//go func(request ziface.IRequest) {
// //从路由中,找到注册绑定的conn对应的router 调用
// c.Router.PreHandle(request)
// c.Router.Handle(request)
// c.Router.PostHandle(request)
//}(&req)
if utils.GlobalObject.WokePoolSize > 0 {
//已经开启工作池,将消息发给工作池
c.MsgHandler.SendMsgTaskQueue(&req)
} else {
//根据绑定msgID找到对应处理api业务执行
go c.MsgHandler.DoMsgHandler(&req)
}
}
}
// StartWriter写消息 goroutine, 专门发送给客户端消息的模块
func (c *Connection) StartWriter() {
fmt.Println("[Writer GoRoutine is Running...]")
defer fmt.Println(c.RemoteAddr().String(), " conn writering exit")
//不断阻塞的等待channel的消息
for {
select {
case data := <-c.msgChan:
if _, err := c.Conn.Write(data); err != nil {
fmt.Println("send data error ", err)
return
}
case <-c.ExitChan:
//代表已经退出,writer 也要退出
return
}
}
}
// Start 启动链接
func (c *Connection) Start() {
fmt.Println("conn start() ...conn:", c.ConnID)
//处理业务数据
go c.StartReader()
go c.StartWriter()
//按照开发者传递进来的 创建连接之后需要调用的处理业务对应执行hook 函数
c.TcpServer.CallOnConnStart(c)
}
// Stop 关闭连接
func (c *Connection) Stop() {
fmt.Println("conn stop .....,connID:", c.ConnID)
if c.isClosed == true {
return
}
c.isClosed = true
//调用开发者注册销毁连接之前执行的hook 函数
c.TcpServer.CallOnConnStop(c)
//关闭连接
c.Conn.Close()
//告知writer 关闭
c.ExitChan <- true
//将conn 删除掉
c.TcpServer.GetConnMgr().Remove(c)
//关闭资源
close(c.ExitChan)
close(c.msgChan)
}
// GetTcpConnection 获取当前链接绑定的socket
func (c *Connection) GetTcpConnection() *net.TCPConn {
return c.Conn
}
// GetConnectionID 获取当前链接模块的ID
func (c *Connection) GetConnectionID() uint32 {
return c.ConnID
}
// RemoteAddr 获取远程客户点的tcp 状态 ip port
func (c *Connection) RemoteAddr() net.Addr {
return c.Conn.RemoteAddr()
}
// Send 发送数据,将数据发送给远程客户端,先封包在发送
func (c *Connection) SendMsg(msgId uint32, data []byte) error {
if c.isClosed == true {
return errors.New("connection close when send msg")
}
//将data 在封包
dp := NewDataPack()
binaryMsg, err := dp.Pack(NewMessage(msgId, data))
if err != nil {
fmt.Println("pack msg id = ", msgId)
return errors.New("pack err msg")
}
//将数据发送到客户端
//if _, err := c.Conn.Write(binaryMsg); err != nil {
// fmt.Println("write msg id = ", msgId)
// return errors.New("write msg err")
//}
c.msgChan <- binaryMsg
return nil
}
// 设置连接属性
func (c *Connection) SetProperty(key string, value interface{}) {
c.propertyLock.Lock()
defer c.propertyLock.Unlock()
//添加一个连接属性
c.property[key] = value
}
// 获取连接属性
func (c *Connection) GetProperty(key string) (interface{}, error) {
c.propertyLock.RLock()
defer c.propertyLock.RUnlock()
if value, ok := c.property[key]; ok {
return value, nil
} else {
return nil, errors.New("not property found")
}
}
// 移除连接属性
func (c *Connection) RemoveProperty(key string) {
c.propertyLock.Lock()
defer c.propertyLock.Unlock()
//删除
delete(c.property, key)
}

71
znet/datapack.go Normal file
View File

@ -0,0 +1,71 @@
package znet
import (
"bytes"
"encoding/binary"
"errors"
"zinx/utils"
"zinx/ziface"
)
/**
*/
type DataPack struct {
}
// 初始化示例
func NewDataPack() *DataPack {
return &DataPack{}
}
// 获取包的头长度方法
func (d *DataPack) GetHeadLen() uint32 {
//datalen uint32(4个字节) +id (4个字节)
return 8
}
// 封包方法
func (d *DataPack) Pack(msg ziface.IMessage) ([]byte, error) {
//创建bytes字节缓冲
dataBuf := bytes.NewBuffer([]byte{})
//将datalen 写入buf
if err := binary.Write(dataBuf, binary.LittleEndian, msg.GetDataLen()); err != nil {
return nil, err
}
//将msgid写入buf
if err := binary.Write(dataBuf, binary.LittleEndian, msg.GetMsgId()); err != nil {
return nil, err
}
//将data写入buf
if err := binary.Write(dataBuf, binary.LittleEndian, msg.GetData()); err != nil {
return nil, err
}
return dataBuf.Bytes(), nil
}
// 拆包方法 先读head 长度 ,根据head 长度读取内容
func (d *DataPack) UnPack(binaryData []byte) (ziface.IMessage, error) {
//创建bytes字节缓冲
dataBuf := bytes.NewReader(binaryData)
//直解压 head 获取datalen 与 msgid
msg := &Message{}
//读取datalen
if err := binary.Read(dataBuf, binary.LittleEndian, &msg.DataLen); err != nil {
return nil, err
}
//读取msgId
if err := binary.Read(dataBuf, binary.LittleEndian, &msg.Id); err != nil {
return nil, err
}
//判断datalen是否超出最大包的限制
if utils.GlobalObject.MaxPackageSize > 0 && msg.DataLen > utils.GlobalObject.MaxPackageSize {
return nil, errors.New("too large data recv")
}
return msg, nil
}

49
znet/message.go Normal file
View File

@ -0,0 +1,49 @@
package znet
type Message struct {
//消息的id
Id uint32
//消息的内容的长度
DataLen uint32
//消息的内容
Data []byte
}
func NewMessage(id uint32, data []byte) *Message {
return &Message{
Id: id,
Data: data,
DataLen: uint32(len(data)),
}
}
// GetMsgId 获取消息的id
func (m *Message) GetMsgId() uint32 {
return m.Id
}
// GetDataLen 获取消息的长度
func (m *Message) GetDataLen() uint32 {
return m.DataLen
}
// GetData 获取消息的内容
func (m *Message) GetData() []byte {
return m.Data
}
// SetMsgId 设置消息的id
func (m *Message) SetMsgId(id uint32) {
m.Id = id
}
// SetDataLen 设置消息的长度
func (m *Message) SetDataLen(dataLen uint32) {
m.DataLen = dataLen
}
// SetData 设置消息的内容
func (m *Message) SetData(data []byte) {
m.Data = data
}

99
znet/messageHandler.go Normal file
View File

@ -0,0 +1,99 @@
package znet
import (
"fmt"
"strconv"
"zinx/utils"
"zinx/ziface"
)
/**
*/
type MsgHandler struct {
//存放每个msgId 对应的处理方法
Apis map[uint32]ziface.IRouter
//负责worker 取任务的消息对列
TaskQueue []chan ziface.IRequest
//业务工作池的数量
WorkPoolSize uint32
}
// 添加初始化方法
func NewMsgHandler() *MsgHandler {
return &MsgHandler{
Apis: make(map[uint32]ziface.IRouter),
WorkPoolSize: utils.GlobalObject.WokePoolSize,
TaskQueue: make([]chan ziface.IRequest, utils.GlobalObject.WokePoolSize),
}
}
// 调度/执行队形router 消息处理方法
func (msgHandler *MsgHandler) DoMsgHandler(request ziface.IRequest) {
//request 获取msgId
router, ok := msgHandler.Apis[request.GetMsgId()]
if !ok {
fmt.Println("api msg id = ", request.GetMsgId(), " is not found , need register")
return
}
//根据路由调用对应的业务
router.PreHandle(request)
router.Handle(request)
router.PostHandle(request)
}
// 为消息添加具体的处理模块
func (msgHandler *MsgHandler) AddRouter(msgId uint32, router ziface.IRouter) {
//判断msg 绑定的api 是否存在
if _, ok := msgHandler.Apis[msgId]; ok {
//id已经注册过
panic("repeat api , msgId = " + strconv.Itoa(int(msgId)))
}
//添加对应关系
msgHandler.Apis[msgId] = router
fmt.Println("add api msgid = ", msgId, " successful")
}
// StartWorkPool 启动一个worker 工作池,(开启工作池只能发生一次,一个zinx 框架只能有一个工作池)
func (msgHandler *MsgHandler) StartWorkPool() {
//根据workpoolsize分别开启worker,每个worker 用一个go 承载
for i := 0; i < int(msgHandler.WorkPoolSize); i++ {
//1.当前worker对应channel 的消息队列 , 开启空间 , 第0个worker 对应 第0 个channel..
msgHandler.TaskQueue[i] = make(chan ziface.IRequest, utils.GlobalObject.MaxWorkerTaskLen)
fmt.Println("i = ", i, "taskQueue = ", msgHandler.TaskQueue[i])
//启动当前worker,阻塞等待消息从channel中传递过来
go msgHandler.StartOneWorker(i, msgHandler.TaskQueue[i])
}
}
// StartOneWorker 启动一个worker 工作流程
func (msgHandler *MsgHandler) StartOneWorker(workerId int, taskQueue chan ziface.IRequest) {
fmt.Println("Worker ID = ", workerId, " is starting ...")
//不断阻塞等待消息
for {
select {
case request := <-taskQueue:
msgHandler.DoMsgHandler(request)
}
}
}
// 将消息交给taskQueue, 由worker 处理
func (msgHander *MsgHandler) SendMsgTaskQueue(request ziface.IRequest) {
//将消息平均分配 给worker(根据ConnectionID 进行分配)
workerID := request.GetConnection().GetConnectionID() % msgHander.WorkPoolSize
fmt.Println("add connID = ", request.GetConnection().GetConnectionID(), " request MsgId = ", request.GetMsgId(), " to worker id =", workerID)
//将消息发送给对应worker的taskQUeue即可
msgHander.TaskQueue[workerID] <- request
fmt.Println("msgHander.TaskQueue[workerID] = ", workerID)
}

27
znet/request.go Normal file
View File

@ -0,0 +1,27 @@
package znet
import "zinx/ziface"
type Request struct {
//客户端链接
conn ziface.IConnection
//客户端的请求数据
msg ziface.IMessage
}
// GetConnection 获取连接
func (r *Request) GetConnection() ziface.IConnection {
return r.conn
}
// GetData 请求的消息数据
func (r *Request) GetData() []byte {
return r.msg.GetData()
}
// 获取请求消息的id
func (r *Request) GetMsgId() uint32 {
return r.msg.GetMsgId()
}

21
znet/router.go Normal file
View File

@ -0,0 +1,21 @@
package znet
import "zinx/ziface"
type BaseRouter struct {
}
// PreHandle 在处理conn 业务之前的钩子方法 hook
func (br *BaseRouter) PreHandle(request ziface.IRequest) {
}
// Handle 在处理conn 业务的主方法hook
func (br *BaseRouter) Handle(request ziface.IRequest) {
}
// PostHandle 在处理conn业务之后的钩子方法
func (br *BaseRouter) PostHandle(request ziface.IRequest) {
}

188
znet/server.go Normal file
View File

@ -0,0 +1,188 @@
package znet
import (
"errors"
"fmt"
"net"
"zinx/utils"
"zinx/ziface"
)
// Server /*
/**
IServer ,Serve
*/
type Server struct {
//服务器名称
Name string
//服务器绑定的ip版本
IPVersion string
//服务器监听的ip地址
IP string
//f服务器监听的端口
Port int
//当前Server由用户绑定的回调router,也就是Server注册的链接对应的处理业务
MsgHandler ziface.IMsgHandler
//该server 的连接管理器
ConnMgr ziface.IConnManager
//该server创建之后自动调用的hook 函数 -- OnConnStart
OnConnStart func(conn ziface.IConnection)
//该server销毁连接之前自动调用的hook 函数 -- OnConnStop
OnConnStop func(conn ziface.IConnection)
}
//实现IServer 接口
func (s *Server) Start() {
fmt.Printf("[Zinx GlobalObject] Server Name : %s,Ip : %s,Port : %d\n",
utils.GlobalObject.Name, utils.GlobalObject.Host, utils.GlobalObject.TcpPort)
fmt.Printf("[Zinx GlobalObject] Version Name : %s,MaxConn : %d,MaxPackageSize : %d\n",
utils.GlobalObject.Version, utils.GlobalObject.MaxConn, utils.GlobalObject.MaxPackageSize)
fmt.Printf("[Start] Server Listenner at Ip :%s ,Port %d, is startring \n", s.IP, s.Port)
go func() {
//开启worker 消息队列几工作池
s.MsgHandler.StartWorkPool()
//1.获取tcp地址
addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
if err != nil {
fmt.Println("resplve tcp addr error :", err)
}
//2.监听服务器地址
listenner, err := net.ListenTCP(s.IPVersion, addr)
if err != nil {
fmt.Println("listen ", s.IPVersion, " error", err)
}
fmt.Println("start zinx server ", s.Name, "successful listenning")
//3.阻塞等待客户端链接,处理客户端连接请求
var cid uint32
cid = 0
for {
//如果有客户端连接,阻塞返回
conn, err := listenner.AcceptTCP()
if err != nil {
fmt.Println("accept error", err)
continue
}
////已经建立客户端连接,处理数据
//go func() {
// for {
// buf := make([]byte, 512)
// len, err2 := conn.Read(buf)
// if err2 != nil {
// fmt.Println("recv buf error", err)
// continue
// }
//
// fmt.Printf("recv buf:%s,len:%d\n", string(buf[:len]), len)
// //回显功能
// if _, err := conn.Write(buf[:len]); err != nil {
// fmt.Println("write back buf error ", err)
// continue
// }
// }
//}()
//设置最大连接个数判断,如果超过最大连接,那么关闭次新的连接
if s.ConnMgr.Len() >= utils.GlobalObject.MaxConn {
//todo 给客户端响应超出最大连接数,错误包
fmt.Println("Too Many Connections MaxConn = ", utils.GlobalObject.MaxConn)
conn.Close()
continue
}
//处理新连接的业务和方法与conn 进行绑定 的到链接模块
dealConn := NewConnection(s, conn, cid, s.MsgHandler)
cid++
go dealConn.Start()
}
}()
}
func CallBackToClient(conn *net.TCPConn, data []byte, cnt int) error {
//回显业务
fmt.Println("[Conn Handle] CallBackToClient ... ")
if _, err := conn.Write(data[:cnt]); err != nil {
fmt.Println("write back buf err ", err)
return errors.New("CallBackToClient error")
}
return nil
}
func (s *Server) Stop() {
//将服务的资源,状态,链接信息进行停止,或回收
fmt.Println("[Stop] zinx Server name = ", s.Name)
s.ConnMgr.ClearConn()
}
func (s *Server) Serve() {
//启动server
s.Start()
//TODO 启动服务之后一些扩展业务
//阻塞
select {}
}
func (s *Server) AddRouter(msgId uint32, router ziface.IRouter) {
s.MsgHandler.AddRouter(msgId, router)
fmt.Println("add router successful")
}
// NewServer 初始化serve
func NewServer() ziface.IServer {
s := &Server{
Name: utils.GlobalObject.Name,
IPVersion: "tcp4",
IP: utils.GlobalObject.Host,
Port: utils.GlobalObject.TcpPort,
MsgHandler: NewMsgHandler(),
ConnMgr: NewConnManager(),
}
return s
}
func (s *Server) GetConnMgr() ziface.IConnManager {
return s.ConnMgr
}
// SetOnConnStart 注册OnConnStat 钩子函数方法
func (s *Server) SetOnConnStart(hookFunc func(connection ziface.IConnection)) {
s.OnConnStart = hookFunc
}
// SetOnConnStop 注册OnConnStop 钩子函数方法
func (s *Server) SetOnConnStop(hookFunc func(connection ziface.IConnection)) {
s.OnConnStop = hookFunc
}
// CallOnConnStart 调用OnConnStat 钩子函数方法
func (s *Server) CallOnConnStart(conn ziface.IConnection) {
if s.OnConnStart != nil {
fmt.Println("-----> CallOnConnStart() ....")
s.OnConnStart(conn)
}
}
// CallOnConnStop 调用OnConnStop 钩子函数方法
func (s *Server) CallOnConnStop(conn ziface.IConnection) {
if s.OnConnStop != nil {
fmt.Println("-----> CallOnConnStop() ....")
s.OnConnStop(conn)
}
}