diff --git a/README.md b/README.md index 49536b3..dcf7f94 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,219 @@ Zinx框架的项目制作采用编码和学习教程同步进行,将开发的 ## 三、Zinx详细教程(代码教程同步更新) [《Zinx框架教程-基于Golang的轻量级并发服务器》](https://www.jianshu.com/p/23d07c0a28e5) +## 四、Zinx开发API文档 + +### 快速开始 + +#### server +基于Zinx框架开发的服务器应用,主函数步骤比较精简,最多主需要4步即可。 +1. 创建server句柄 +2. 配置自定义路由及业务 +3. 启动服务 + +```go +func main() { + //1 创建一个server句柄 + s := znet.NewServer() + + //2 配置路由 + s.AddRouter(0, &PingRouter{}) + + //3 开启服务 + s.Serve() +} +``` + +其中自定义路由及业务配置方式如下: +```go +import ( + "fmt" + "zinx/ziface" + "zinx/znet" +) + +//ping test 自定义路由 +type PingRouter struct { + znet.BaseRouter +} + +//Ping Handle +func (this *PingRouter) Handle(request ziface.IRequest) { + //先读取客户端的数据 + fmt.Println("recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData())) + + //再回写ping...ping...ping + err := request.GetConnection().SendBuffMsg(0, []byte("ping...ping...ping")) + if err != nil { + fmt.Println(err) + } +} +``` + +#### client +Zinx的消息处理采用,`[MsgLength]|[MsgID]|[Data]`的封包格式 +```go +package main + +import ( + "fmt" + "io" + "net" + "time" + "zinx/znet" +) + +/* + 模拟客户端 + */ +func main() { + + fmt.Println("Client Test ... start") + //3秒之后发起测试请求,给服务端开启服务的机会 + time.Sleep(3 * time.Second) + + conn,err := net.Dial("tcp", "127.0.0.1:7777") + if err != nil { + fmt.Println("client start err, exit!") + return + } + + for n := 3; n >= 0; n-- { + //发封包message消息 + dp := znet.NewDataPack() + msg, _ := dp.Pack(znet.NewMsgPackage(0,[]byte("Zinx Client Test Message"))) + _, err := conn.Write(msg) + if err !=nil { + fmt.Println("write error err ", err) + return + } + + //先读出流中的head部分 + headData := make([]byte, dp.GetHeadLen()) + _, err = io.ReadFull(conn, headData) //ReadFull 会把msg填充满为止 + if err != nil { + fmt.Println("read head error") + break + } + //将headData字节流 拆包到msg中 + msgHead, err := dp.Unpack(headData) + if err != nil { + fmt.Println("server unpack err:", err) + return + } + + if msgHead.GetDataLen() > 0 { + //msg 是有data数据的,需要再次读取data数据 + msg := msgHead.(*znet.Message) + msg.Data = make([]byte, msg.GetDataLen()) + + //根据dataLen从io中读取字节流 + _, err := io.ReadFull(conn, msg.Data) + if err != nil { + fmt.Println("server unpack data err:", err) + return + } + + fmt.Println("==> Recv Msg: ID=", msg.Id, ", len=", msg.DataLen, ", data=", string(msg.Data)) + } + + time.Sleep(1*time.Second) + } +} +``` + +### Zinx配置文件 +```json +{ + "Name":"Zinx Game", + "Host":"0.0.0.0", + "TcpPort":8999, + "MaxConn":3000, + "WorkerPoolSize":10 +} +``` +`Name`:服务器应用名称 +`Host`:服务器IP +`TcpPort`:服务器监听端口 +`MaxConn`:允许的客户端链接最大数量 +`WorkerPoolSize`:工作任务池最大工作Goroutine数量 + +###I.服务器模块Server +```go + func NewServer () ziface.IServer +``` +创建一个Zinx服务器句柄,该句柄作为当前服务器应用程序的主枢纽,包括如下功能: + +####1) 开启服务 +```go + func (s *Server) Start() +``` +####2) 停止服务 +```go + func (s *Server) Stop() +``` +####3) 运行服务 +```go + func (s *Server) Serve() +``` +####4) 注册路由 +```go +func (s *Server) AddRouter (msgId uint32, router ziface.IRouter) +``` +####5) 注册链接创建Hook函数 +```go +func (s *Server) SetOnConnStart(hookFunc func (ziface.IConnection)) +``` +####6) 注册链接销毁Hook函数 +```go +func (s *Server) SetOnConnStop(hookFunc func (ziface.IConnection)) +``` +###II. 路由模块 + +```go +//实现router时,先嵌入这个基类,然后根据需要对这个基类的方法进行重写 +type BaseRouter struct {} + +//这里之所以BaseRouter的方法都为空, +// 是因为有的Router不希望有PreHandle或PostHandle +// 所以Router全部继承BaseRouter的好处是,不需要实现PreHandle和PostHandle也可以实例化 +func (br *BaseRouter)PreHandle(req ziface.IRequest){} +func (br *BaseRouter)Handle(req ziface.IRequest){} +func (br *BaseRouter)PostHandle(req ziface.IRequest){} +``` + + +###III. 链接模块 +####1) 获取原始的socket TCPConn +```go + func (c *Connection) GetTCPConnection() *net.TCPConn +``` +####2) 获取链接ID +```go + func (c *Connection) GetConnID() uint32 +``` +####3) 获取远程客户端地址信息 +```go + func (c *Connection) RemoteAddr() net.Addr +``` +####4) 发送消息 +```go + func (c *Connection) SendMsg(msgId uint32, data []byte) error + func (c *Connection) SendBuffMsg(msgId uint32, data []byte) error +``` +####5) 链接属性 +```go +//设置链接属性 +func (c *Connection) SetProperty(key string, value interface{}) + +//获取链接属性 +func (c *Connection) GetProperty(key string) (interface{}, error) + +//移除链接属性 +func (c *Connection) RemoveProperty(key string) +``` + + --- ###关于作者: diff --git a/znet/server.go b/znet/server.go index 02f2c83..d1edbac 100644 --- a/znet/server.go +++ b/znet/server.go @@ -105,6 +105,7 @@ func (s *Server) Start() { }() } +//停止服务 func (s *Server) Stop() { fmt.Println("[STOP] Zinx server , name " , s.Name) @@ -112,6 +113,7 @@ func (s *Server) Stop() { s.ConnMgr.ClearConn() } +//运行服务 func (s *Server) Serve() { s.Start()