go-study/zinx/znet/server.go
2025-09-14 18:12:02 +08:00

154 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package znet
import (
"fmt"
"go-study/zinx/utils"
"go-study/zinx/ziface"
"net"
)
type Server struct {
// Name 服务器名称
Name string
// IPVersion tcp4 or tcp6
IPVersion string
// IP 服务器监听的 IP
IP string
// Port 服务器监听的端口
Port int
// msgHandler 该服务器的消息管理模块,用来绑定 MsgID 和对应的处理方法
msgHandler ziface.IMsgHandle
// connMgr 该服务器的连接管理器
connMgr ziface.IConnManager
// onConnStart 该服务器的连接创建时 Hook 函数
onConnStart func(conn ziface.IConnection)
// onConnStop 该服务器的连接断开时的 Hook 函数
onConnStop func(conn ziface.IConnection)
}
// NewServer 创建一个服务器句柄
func NewServer() ziface.IServer {
utils.ConfigInstance.Reload()
return &Server{
Name: utils.ConfigInstance.Name,
IPVersion: "tcp4",
IP: utils.ConfigInstance.Host,
Port: utils.ConfigInstance.TcpPort,
msgHandler: NewMsgHandle(),
connMgr: NewConnManager(),
}
}
// Start 启动服务器
func (s *Server) Start() {
fmt.Printf("[START] Server name: %s, listenner at IP: %s, Port %d, is starting\n", s.Name, s.IP, s.Port)
fmt.Printf("[Zinx] Version %s, MaxConn: %d, MaxPacketSize: %d\n",
utils.ConfigInstance.Version,
utils.ConfigInstance.MaxConn,
utils.ConfigInstance.MaxPacketSize)
go func() {
// 0. 启动消息队列及 worker 工作池
s.msgHandler.StartWorkerPool()
// 1. 获取一个 TCP 的 Addr
addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.Port))
if err != nil {
fmt.Println("resolve tcp addr error:", err)
return
}
// 2. 监听服务器地址
listener, err := net.ListenTCP(s.IPVersion, addr)
if err != nil {
fmt.Println("listen", s.IPVersion, "err", err)
return
}
fmt.Println("start Zinx server ", s.Name, " succ, now listening...")
// TODO 应该有一个自动生成 ID 的方法
cid := uint32(0)
// 3. 阻塞等待客户端连接,处理客户端连接业务(读写)
for {
// 3.1 阻塞等待客户端连接AcceptTCP 会阻塞
conn, err := listener.AcceptTCP()
if err != nil {
fmt.Println("Accept err", err)
continue
}
// 3.2 设置服务器最大连接数,如果超过最大连接数则关闭此新连接
if s.connMgr.Len() >= utils.ConfigInstance.MaxConn {
_ = conn.Close()
continue
}
// 3.3 处理该新连接请求的业务方法,此时 handler 和 conn 应该是绑定的
dealConn := NewConnection(s, conn, cid, s.msgHandler)
cid++
// 3.4 启动当前连接的业务处理
go dealConn.Start()
}
}()
}
// Stop 停止服务器
func (s *Server) Stop() {
fmt.Println("[STOP] Zinx server, name ", s.Name)
// 将需要清理的连接信息或者其他信息一并停止或者清理
s.connMgr.ClearConn()
}
// Serve 运行服务器
func (s *Server) Serve() {
s.Start()
// TODO 做一些启动服务器之后的额外业务
// 阻塞,否则主 Go 程退出listener 会退出
select {}
}
// AddRouter 为当前服务注册一个路由方法,供客户端连接处理使用
func (s *Server) AddRouter(msgID uint32, router ziface.IRouter) {
s.msgHandler.AddRouter(msgID, router)
fmt.Println("Add Router Succ!")
}
// GetConnMgr 获取连接管理器
func (s *Server) GetConnMgr() ziface.IConnManager {
return s.connMgr
}
// SetOnConnStart 设置该服务器的连接创建时的钩子函数
func (s *Server) SetOnConnStart(hookFunc func(conn ziface.IConnection)) {
s.onConnStart = hookFunc
}
// SetOnConnStop 设置该服务器的连接断开时的钩子函数
func (s *Server) SetOnConnStop(hookFunc func(conn ziface.IConnection)) {
s.onConnStop = hookFunc
}
// CallOnConnStart 调用连接创建时的钩子函数
func (s *Server) CallOnConnStart(conn ziface.IConnection) {
if s.onConnStart != nil {
fmt.Println("-----> Call OnConnStart()...")
s.onConnStart(conn)
}
}
// CallOnConnStop 调用连接断开时的钩子函数
func (s *Server) CallOnConnStop(conn ziface.IConnection) {
if s.onConnStop != nil {
fmt.Println("-----> Call OnConnStop()...")
s.onConnStop(conn)
}
}