From 2f3ca21165cbd2772f5c6975ecc052ab84cf5637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <1@72wo.cn> Date: Sun, 6 Jul 2025 01:49:19 +0800 Subject: [PATCH] =?UTF-8?q?feat(login):=20=E9=87=8D=E6=9E=84=20login=20?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=90=AF=E5=8A=A8=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改 login 服务端口配置,支持动态分配 - 优化 login 服务启动流程,增加信号处理 - 调整 ServerOption 类型,支持 int 类型端口 - 移除 CommendSvrInfo 相关代码,简化结构 - 更新 main 函数,采用新的服务启动方式 --- .gitignore | 3 +- .vscode/launch.json | 13 ++++- .vscode/tasks.json | 50 +++++++++++++++++ common/cool/coolconfig/config.go | 2 +- common/socket/ServerOption.go | 5 +- logic/controller/getserver.go | 24 +++++++++ logic/main.go | 49 +++++++++++++++-- logic/server.go | 54 +++++++++++++++++++ .../{login => server}/CommendSvrInfo.go | 50 +++++++++++++++-- logic/service/server/sid.go | 11 ++++ login/main.go | 20 +++---- modules/base/base.go | 1 + modules/base/packed/packed.go | 2 +- .../base/resource/initjson/base_sys_conf.json | 10 ++++ modules/base/service/base_sys_conf.go | 5 +- modules/blazing/model/pet.go | 10 ++-- modules/blazing/model/server_list.go | 7 +-- modules/blazing/service/login.go | 21 ++++++++ public/config/ServerR.xml | 9 ---- 19 files changed, 301 insertions(+), 45 deletions(-) create mode 100644 .vscode/tasks.json create mode 100644 logic/controller/getserver.go create mode 100644 logic/server.go rename logic/service/{login => server}/CommendSvrInfo.go (58%) create mode 100644 logic/service/server/sid.go create mode 100644 modules/base/resource/initjson/base_sys_conf.json diff --git a/.gitignore b/.gitignore index df02a75d4..685db15ab 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ data/redis/ go.work.sum __debug_* public/ -frontend/ \ No newline at end of file +frontend/ +*.exe \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index ee8175dc4..0025029bc 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -6,7 +6,7 @@ "configurations": [ { - "name": "Launch login", + "name": "Launch login-http", "type": "go", "request": "launch", "mode": "auto", @@ -19,7 +19,16 @@ "request": "launch", "mode": "auto", "cwd": "${workspaceFolder}", - "args": ["-port=27000"], + "args": ["-port=1"], + "program": "${workspaceFolder}/logic" + }, + { + "name": "Launch login-tcp", + "type": "go", + "request": "launch", + "mode": "auto", + "cwd": "${workspaceFolder}", + "args": ["-port=0"], "program": "${workspaceFolder}/logic" } diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 000000000..ec590c143 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,50 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "go: build both packages in parallel", + "command": "start /B go build ${workspaceFolder}/login && start /B go build ${workspaceFolder}/logic", + "windows": { + "command": "start /B go build ${workspaceFolder}/login && start /B go build ${workspaceFolder}/logic" + }, + "linux": { + "command": "go build ${workspaceFolder}/login & go build ${workspaceFolder}/logic & wait" + }, + "osx": { + "command": "go build ${workspaceFolder}/login & go build ${workspaceFolder}/logic & wait" + }, + "problemMatcher": [ + "$go" + ], + "group": "build", + "detail": "Parallel build of login and logic packages" + }, + { + "type": "go", + "label": "go: build login", + "command": "build", + "args": [ + "${workspaceFolder}/login" + ], + "problemMatcher": [ + "$go" + ], + "group": "build", + "detail": "cd ${workspaceFolder}; go build ${workspaceFolder}/login" + }, + { + "type": "go", + "label": "go: build logic", + "command": "build", + "args": [ + "${workspaceFolder}/logic" + ], + "problemMatcher": [ + "$go" + ], + "group": "build", + "detail": "cd ${workspaceFolder}; go build ${workspaceFolder}/logic" + } + ] +} \ No newline at end of file diff --git a/common/cool/coolconfig/config.go b/common/cool/coolconfig/config.go index abb71ea7f..16e9c0218 100644 --- a/common/cool/coolconfig/config.go +++ b/common/cool/coolconfig/config.go @@ -9,7 +9,7 @@ type sConfig struct { File *file `json:"file,omitempty"` // 文件上传配置 Name string `json:"name"` // 项目名称 Port string `json:"port"` - PortBL string `json:"port_bl"` + PortBL uint32 `json:"port_bl"` } // OSS相关配置 diff --git a/common/socket/ServerOption.go b/common/socket/ServerOption.go index 329eb4deb..48f7fa69f 100644 --- a/common/socket/ServerOption.go +++ b/common/socket/ServerOption.go @@ -4,6 +4,7 @@ import ( "blazing/common/socket/codec" "blazing/common/socket/handler" + "github.com/gogf/gf/v2/util/gconv" "github.com/panjf2000/gnet/pkg/pool/goroutine" "github.com/panjf2000/gnet/v2" ) @@ -60,10 +61,10 @@ func WithBufferSize(bufferSize int) Option { u.bufferSize = bufferSize } } -func WithPort(port string) Option { +func WithPort(port int) Option { return func(s *Server) { s.network = "tcp" - s.addr = ":" + port + s.addr = ":" + gconv.String(port) } } diff --git a/logic/controller/getserver.go b/logic/controller/getserver.go new file mode 100644 index 000000000..5aab4bd6f --- /dev/null +++ b/logic/controller/getserver.go @@ -0,0 +1,24 @@ +package controller + +import ( + "blazing/common/core" + "blazing/logic/service/server" + "fmt" + + "github.com/panjf2000/gnet/v2" +) + +// 处理命令: 105 +func (h Controller) GetServer(data server.SidInfo, c gnet.Conn) []byte { //这个时候player应该是空的 + + fmt.Println(data.Sid) + + ret := server.NewCommendSvrInfo() + + ret.ServerList = server.GetServerInfoList() + + tt := core.Pack(data.Head, ret) + //fmt.Println(hex.EncodeToString(tt)) + // c.Write(tt) + return tt +} diff --git a/logic/main.go b/logic/main.go index 9a25b5f3f..15c63f7dc 100644 --- a/logic/main.go +++ b/logic/main.go @@ -1,29 +1,70 @@ package main import ( + "fmt" + "log" + "os" + _ "github.com/gogf/gf/contrib/nosql/redis/v2" + "github.com/gogf/gf/v2/os/gproc" + + _ "blazing/contrib/drivers/pgsql" + "github.com/gogf/gf/v2/os/gcmd" + "github.com/gogf/gf/v2/util/gconv" "blazing/common/socket" "blazing/common/socket/handler" "blazing/cool" "blazing/logic/controller" + //"blazing/o/service" + + "blazing/modules/blazing/service" + "github.com/gogf/gf/v2/os/gctx" ) +func signalHandlerForMain(sig os.Signal) { + fmt.Println("MainProcess is shutting down due to signal:", sig.String()) +} + func main() { // 解析命令行参数 - cool.Config.PortBL = gcmd.GetOpt("port", "27000").String() + cool.Config.PortBL = gcmd.GetOpt("port", "1").Uint32() if cool.IsRedisMode { go cool.ListenFunc(gctx.New()) } - Start(cool.Config.PortBL) //注入service + go Start(cool.Config.PortBL) //注入service + fmt.Println("Process start, pid:", os.Getpid()) + gproc.AddSigHandlerShutdown( + + signalHandlerForMain, + ) + + gproc.Listen() } -func Start(port string) { + +// 如果id是0,那就是login server +func Start(serverid uint32) { head := handler.NewTomeeHandler() head.Callback = controller.Recv - socket.NewServer(socket.WithPort(port), socket.WithCORS(), socket.WithSocketHandler(head)).Start() + if serverid != 0 { + // 确定端口 + port, err := determinePort(serverid) + if err != nil { + log.Fatalf("Failed to determine port: %v", err) + } + + //随机端口产生,然后给sql注册端口 + service.NewLoginServiceService().SetServerID(serverid, gconv.Uint16(port)) + socket.NewServer(socket.WithCORS(), socket.WithPort(port), socket.WithSocketHandler(head)).Start() + + } else { + + socket.NewServer(socket.WithCORS(), socket.WithPort(defaultPort), socket.WithSocketHandler(head)).Start() + } + } diff --git a/logic/server.go b/logic/server.go new file mode 100644 index 000000000..fe988e0c9 --- /dev/null +++ b/logic/server.go @@ -0,0 +1,54 @@ +package main + +import ( + "blazing/cool" + "fmt" + "log" + "math/rand" + "net" + "time" + + "github.com/gogf/gf/v2/util/gconv" +) + +const ( + minRandomPort = 10000 + maxRandomPort = 60000 + maxPortRetryCount = 5 +) + +var defaultPort = gconv.Int(cool.Config.Port) //读入默认的端口 + +// determinePort 确定服务器使用的端口 +func determinePort(serverid uint32) (int, error) { + rand.Seed(time.Now().UnixNano()) + if serverid == 0 { + return defaultPort, nil + } + + for i := 0; i < maxPortRetryCount; i++ { + port := generateRandomPort() + if isPortAvailable(port) { + return port, nil + } + log.Printf("Port %d is not available, retrying...", port) + } + + return 0, fmt.Errorf("failed to find available port after %d attempts", maxPortRetryCount) +} + +// generateRandomPort 生成指定范围内的随机端口 +func generateRandomPort() int { + return minRandomPort + rand.Intn(maxRandomPort-minRandomPort) +} + +// isPortAvailable 检查端口是否可用 +func isPortAvailable(port int) bool { + address := fmt.Sprintf(":%d", port) + listener, err := net.Listen("tcp", address) + if err != nil { + return false + } + defer listener.Close() + return true +} diff --git a/logic/service/login/CommendSvrInfo.go b/logic/service/server/CommendSvrInfo.go similarity index 58% rename from logic/service/login/CommendSvrInfo.go rename to logic/service/server/CommendSvrInfo.go index 8e97345e2..61ced619b 100644 --- a/logic/service/login/CommendSvrInfo.go +++ b/logic/service/server/CommendSvrInfo.go @@ -1,9 +1,15 @@ -package login +package server + +import ( + "blazing/cool" + "blazing/modules/base/service" + "blazing/modules/blazing/model" +) // CommendSvrInfo 初始连接请求信息结构体 type CommendSvrInfo struct { //Handler handler.TomeeHeader //` struc:"[0]pad"` //消息头 ,这里为传入的头部数据,遍历此头部实现解析CommendSvrInfo - MaxOnlineID uint32 // 最大连接数 + MaxOnlineID uint32 `struc:"sizeof=ServerList"` // 最大连接数 IsVip uint32 // 建议为0 ServerInfoLen uint32 `struc:"sizeof=ServerList"` // 服务器信息长度 ServerInfo ServerList []ServerInfo // 服务器具体信息 @@ -16,7 +22,7 @@ type CommendSvrInfo struct { func NewCommendSvrInfo() *CommendSvrInfo { return &CommendSvrInfo{ // Handler: handler.TomeeHeader{}, - MaxOnlineID: 100, + // MaxOnlineID: 100, IsVip: 0, ServerInfoLen: 0, ServerList: make([]ServerInfo, 0), @@ -41,8 +47,42 @@ type ServerInfo struct { } // NewServerInfo 创建新的服务器信息实例 -func NewServerInfo() *ServerInfo { - return &ServerInfo{} +func newServerInfo() *ServerInfo { + //getServerInfoList() + return &ServerInfo{ + //OnlineID: 0, + UserCnt: 20, + //IP: "", + // Port: 0, + Friends: 1, + } +} + +func GetServerInfoList() []ServerInfo { + dictInfoModel1 := model.NewServerList() + mType := cool.DBM(dictInfoModel1) + t, _ := mType.All() + //fmt.Println(t) + var ret []model.ServerList + t.Structs(&ret) + //fmt.Println(t) + var ret1 []ServerInfo + ip := service.NewBaseSysConfService().GetValue("server_ip") + + for _, v := range ret { + tt := newServerInfo() + tt.OnlineID = v.OnlineID + // tt.UserCnt = v.UserCnt + //tt.IP = v.IP + tt.IP = ip + tt.Port = v.Port + // tt.Friends = v.Friends + ret1 = append(ret1, *tt) + + } + + return ret1 + } type FriendInfo struct { diff --git a/logic/service/server/sid.go b/logic/service/server/sid.go new file mode 100644 index 000000000..9eda248fe --- /dev/null +++ b/logic/service/server/sid.go @@ -0,0 +1,11 @@ +package server + +import "blazing/common/socket/handler" + +type SidInfo struct { //这里直接使用组合来实现将传入的原始头部数据和结构体参数序列化 + Head handler.TomeeHeader `cmd:"105" struc:"[0]pad"` //玩家登录 + + Sid []byte `struc:"[20]byte"` // 登录会话ID,固定长度16字节 + // NotLogin uint32 `error="10001"|struc:"[0]pad"` //返回错误码 ,不序列化,仅作为错误码 + // ErrorPassWord uint32 `struc:"[0]pad"` +} diff --git a/login/main.go b/login/main.go index 994287162..52b8baace 100644 --- a/login/main.go +++ b/login/main.go @@ -2,13 +2,16 @@ package main import ( _ "github.com/gogf/gf/contrib/nosql/redis/v2" + "github.com/gogf/gf/v2/util/gconv" + + _ "blazing/contrib/drivers/pgsql" + "github.com/panjf2000/gnet/v2" "blazing/common/core" "blazing/common/socket" "blazing/common/socket/handler" _ "blazing/contrib/files/local" - "blazing/cool" "blazing/logic/service/login" // Minio,按需启用 @@ -21,8 +24,6 @@ import ( //_ "blazing/contrib/drivers/mysql" - _ "blazing/contrib/drivers/pgsql" - _ "blazing/modules" "github.com/gogf/gf/v2/os/gctx" @@ -31,7 +32,7 @@ import ( ) func main() { - go Start(cool.Config.Port) + // go Start(cool.Config.Port) cmd.Main.Run(gctx.New()) } @@ -39,21 +40,14 @@ func Start(port string) { head := handler.NewTomeeHandler() head.Callback = recv - socket.NewServer(socket.WithPort(port), socket.WithCORS(), socket.WithSocketHandler(head)).Start() + socket.NewServer(socket.WithPort(gconv.Int(port)), socket.WithCORS(), socket.WithSocketHandler(head)).Start() } func recv(c gnet.Conn, data handler.TomeeHeader) { ret := login.NewCommendSvrInfo() - lofin := login.NewServerInfo() - lofin.OnlineID = 1 - lofin.UserCnt = 77 - lofin.IP = "127.0.0.1" - lofin.Port = 27000 - lofin.Friends = 1 - //ret.Handler = data - ret.ServerList = append(ret.ServerList, *lofin) + ret.ServerList = login.GetServerInfoList() tt := core.Pack(data, ret) //fmt.Println(hex.EncodeToString(tt)) diff --git a/modules/base/base.go b/modules/base/base.go index 3cb1220ea..c87750eb7 100644 --- a/modules/base/base.go +++ b/modules/base/base.go @@ -28,6 +28,7 @@ func init() { cool.FillInitData(ctx, "base", &model.BaseSysDepartment{}) cool.FillInitData(ctx, "base", &model.BaseSysRoleDepartment{}) cool.FillInitData(ctx, "base", &model.BaseSysParam{}) + cool.FillInitData(ctx, "base", &model.BaseSysConf{}) g.Log().Debug(ctx, "module base init finished ...") diff --git a/modules/base/packed/packed.go b/modules/base/packed/packed.go index a3c137235..50ff1c781 100644 --- a/modules/base/packed/packed.go +++ b/modules/base/packed/packed.go @@ -3,7 +3,7 @@ package packed import "github.com/gogf/gf/v2/os/gres" func init() { - if err := gres.Add("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"); err != nil { + if err := gres.Add("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"); err != nil { panic("add binary content to resource manager failed: " + err.Error()) } } diff --git a/modules/base/resource/initjson/base_sys_conf.json b/modules/base/resource/initjson/base_sys_conf.json new file mode 100644 index 000000000..21d3b0334 --- /dev/null +++ b/modules/base/resource/initjson/base_sys_conf.json @@ -0,0 +1,10 @@ +[ + { + "id": 1, + "createTime": "2021-02-26 13:53:05.000000", + "updateTime": "2021-03-03 17:50:04.000000", + + "cKey": "server_ip", + "cValue": "127.0.0.1" + } +] \ No newline at end of file diff --git a/modules/base/service/base_sys_conf.go b/modules/base/service/base_sys_conf.go index 4e943d11a..7e8f32e29 100644 --- a/modules/base/service/base_sys_conf.go +++ b/modules/base/service/base_sys_conf.go @@ -43,7 +43,10 @@ func (s *BaseSysConfService) UpdateValue(cKey, cValue string) error { // GetValue 获取配置值 func (s *BaseSysConfService) GetValue(cKey string) string { - m := cool.DBM(s.Model).Where("cKey = ?", cKey) + + // t1, _ := cool.DBM(s.Model).All() + // fmt.Println(t1) + m := cool.DBM(s.Model).Where("cKey", cKey) record, err := m.One() if err != nil { return "" diff --git a/modules/blazing/model/pet.go b/modules/blazing/model/pet.go index dda5efa85..b61347a11 100644 --- a/modules/blazing/model/pet.go +++ b/modules/blazing/model/pet.go @@ -2,7 +2,6 @@ package model import ( "blazing/cool" - "fmt" ) const TableNamePet = "pet" @@ -57,6 +56,11 @@ type PetInfo struct { FreedTime string `gorm:"comment:'放生时间'" json:"freed_time"` } +type PetSkillInfo struct { + skill int32 `gorm:"not null;default:0;comment:'技能1'" json:"skill_1_id"` + pp int16 `gorm:"not null;default:0;comment:'技能1PP'" json:"skill_1_pp"` +} + // TableName Pet's table name func (*Pet) TableName() string { return TableNamePet @@ -76,6 +80,6 @@ func NewPet() *Pet { // init 创建表 func init() { - err := cool.CreateTable(&Pet{}) - fmt.Println(err) + _ = cool.CreateTable(&Pet{}) + // fmt.Println(err) } diff --git a/modules/blazing/model/server_list.go b/modules/blazing/model/server_list.go index 53ae382a3..db808353d 100644 --- a/modules/blazing/model/server_list.go +++ b/modules/blazing/model/server_list.go @@ -9,9 +9,10 @@ const TableNameServerList = "server_list" // ServerList mapped from table type ServerList struct { *cool.Model - IP string `gorm:"type:varchar(16);comment:'服务器IP'" json:"ip"` - Port uint16 `gorm:"comment:'端口号,通常是小整数'" json:"port"` - IsOpen bool `gorm:"default:true;not null;comment:'服务器是否开启,默认为开启状态'" json:"is_open"` + OnlineID uint32 `gorm:"column:online_id;comment:'在线ID';uniqueIndex" json:"online_id"` + //IP string `gorm:"type:varchar(16);comment:'服务器IP'" json:"ip"` + Port uint16 `gorm:"comment:'端口号,通常是小整数'" json:"port"` + //IsOpen bool `gorm:"default:true;not null;comment:'服务器是否开启,默认为开启状态'" json:"is_open"` } // TableName ServerList's table name diff --git a/modules/blazing/service/login.go b/modules/blazing/service/login.go index bc6c0791c..56431c684 100644 --- a/modules/blazing/service/login.go +++ b/modules/blazing/service/login.go @@ -50,3 +50,24 @@ func (s *LoginService) GetSessionId(accountID uint) (string, string, error) { // /t1. // 以上过程只需全局一次,且应在生成ID之前完成。 } +func (s *LoginService) SetServerID(OnlineID uint32, Port uint16) error { + + m := cool.DBM(s.Model).Where("online_id", OnlineID) + + record, err := m.One() + if err != nil { + return err + } + if record == nil { + //说明是新的服务器 + + _, err := m.InsertAndGetId(&model.ServerList{OnlineID: OnlineID, Port: Port}) + + return err + } + + _, err = m.Data(&model.ServerList{OnlineID: OnlineID, Port: Port}).Where("online_id", OnlineID).Update() + + return nil + +} diff --git a/public/config/ServerR.xml b/public/config/ServerR.xml index 66019d475..996f6e455 100644 --- a/public/config/ServerR.xml +++ b/public/config/ServerR.xml @@ -19,15 +19,6 @@ - - - - - - - - -