Zinx- 基于 Go 的轻量级并发服务器框架

网友投稿 743 2022-10-28

Zinx- 基于 Go 的轻量级并发服务器框架

Zinx- 基于 Go 的轻量级并发服务器框架

Zinx 是一个基于Golang的轻量级并发服务器框架

开发人员

- 刘丹冰(@aceld)- 张超(@zhngcho)

一、写在前面

我们为什么要做Zinx,Golang目前在服务器的应用框架很多,但是应用在游戏领域或者其他长链接的领域的轻量级企业框架甚少。

设计Zinx的目的是我们可以通过Zinx框架来了解基于Golang编写一个TCP服务器的整体轮廓,让更多的Golang爱好者能深入浅出的去学习和认识这个领域。

Zinx框架的项目制作采用编码和学习教程同步进行,将开发的全部递进和迭代思维带入教程中,而不是一下子给大家一个非常完整的框架去学习,让很多人一头雾水,不知道该如何学起。

教程会一个版本一个版本迭代,每个版本的添加功能都是微小的,让一个服务框架小白,循序渐进的曲线方式了解服务器框架的领域。

当然,最后希望Zinx会有更多的人加入,给我们提出宝贵的意见,让Zinx成为真正的解决企业的服务器框架!在此感谢您的关注!

二、初探Zinx架构

三、Zinx详细教程(代码教程同步更新)

《Zinx框架教程-基于Golang的轻量级并发服务器》

四、Zinx开发API文档

快速开始

server

基于Zinx框架开发的服务器应用,主函数步骤比较精简,最多主需要3步即可。1. 创建server句柄2. 配置自定义路由及业务3. 启动服务

func main() {    //1 创建一个server句柄    s := znet.NewServer()    //2 配置路由    s.AddRouter(0, &PingRouter{})    //3 开启服务    s.Serve()}

其中自定义路由及业务配置方式如下:

import (    "fmt"    "zinx/ziface"    "zinx/znet")//ping test 自定义路由type PingRouter struct {    znet.BaseRouter}//Ping Handlefunc (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]**的封包格式

package mainimport (    "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配置文件

{  "Name":"Zinx Game",   "Host":"0.0.0.0",  "TcpPort":8999,  "MaxConn":3000,  "WorkerPoolSize":10}

Name :服务器应用名称

Host :服务器IP

TcpPort :服务器监听端口

MaxConn :允许的客户端链接最大数量

WorkerPoolSize :工作任务池最大工作Goroutine数量

I.服务器模块Server

func NewServer () ziface.IServer

创建一个Zinx服务器句柄,该句柄作为当前服务器应用程序的主枢纽,包括如下功能:

1)开启服务

func (s *Server) Start()

2)停止服务

func (s *Server) Stop()

3)运行服务

func (s *Server) Serve()

4)注册路由

func (s *Server) AddRouter (msgId uint32, router ziface.IRouter)

5)注册链接创建Hook函数

func (s *Server) SetOnConnStart(hookFunc func (ziface.IConnection))

6)注册链接销毁Hook函数

func (s *Server) SetOnConnStop(hookFunc func (ziface.IConnection))

II.路由模块

//实现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

func (c *Connection) GetTCPConnection() *net.TCPConn

2)获取链接ID

func (c *Connection) GetConnID() uint32

3)获取远程客户端地址信息

func (c *Connection) RemoteAddr() net.Addr

4)发送消息

func (c *Connection) SendMsg(msgId uint32, data []byte) error   func (c *Connection) SendBuffMsg(msgId uint32, data []byte) error

5)链接属性

//设置链接属性func (c *Connection) SetProperty(key string, value interface{})//获取链接属性func (c *Connection) GetProperty(key string) (interface{}, error)//移除链接属性func (c *Connection) RemoveProperty(key string)

__

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:php 面试题
下一篇:咱们500万条数据测试一下,如何合理使用索引加速?
相关文章

 发表评论

暂时没有评论,来抢沙发吧~