同步操作将从 刘丹冰Aceld/zinx 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
English | 简体中文
Zinx is a lightweight concurrent server framework based on Golang.
Website:http://zinx.me
ps:
Zinx has been developed and used in many enterprises: Service of message transfer, Persistent Connection TCP/IP Server, The middleware of Web Service and so on. Zinx is positioned for code simplicity, Developers can use Zinx to redevelop a module suitable for their own enterprise scenarios.
Git: https://github.com/aceld/zinx
Git: https://gitee.com/Aceld/zinx
YuQue - Zinx Framework tutorial-Lightweight server based on Golang》
Why are we doing Zinx? There are a lot of frameworks for servers in The Go Programing Language, but very few lightweight enterprise frameworks for games or other persistent connection TCP/IP Server domains.
Zinx is designed so that developers can use the Zinx framework to understand the overall outline of writing a TCP server based on Golang, Let more Gopher can learn and understand this field in a simple way.
The Zinx framework projects are done in parallel with the coding and learning tutorials, bringing all of the progressive and iterative thinking of development into the tutorials, rather than giving everyone a very complete framework to learn at once, leaving many people confused about how to learn.
The tutorial will iterate from release to release, with minor additions to each release, giving a small, curvewise approach to the domain of the server framework.
Of course, I hope that more people will join Zinx and give us valuable suggestions, so that Zinx can become a real solution server framework for enterprises! Thank you for your attention!
The honor of zinx
Version Golang 1.16+
# clone from git
$ git clone https://github.com/aceld/zinx.git
# cd the dir of Demo
$ cd ./zinx/examples/zinx_server
# Build
$ make build
# Build for docker image
$ make image
# start and run
$ make run
# cd the dir of Demo Client
$ cd ../zinx_client
# run
$ go run main.go
zinx/example/zinx_server
, we get server
, in zinx/example/zinx_client
, we getclient
.$ cd zinx/
$ make
$ cd example/zinx_server
$ ./server
██
▀▀
████████ ████ ██▄████▄ ▀██ ██▀
▄█▀ ██ ██▀ ██ ████
▄█▀ ██ ██ ██ ▄██▄
▄██▄▄▄▄▄ ▄▄▄██▄▄▄ ██ ██ ▄█▀▀█▄
▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀ ▀▀ ▀▀ ▀▀▀ ▀▀▀
┌───────────────────────────────────────────────────┐
│ [Github] https://github.com/aceld │
│ [tutorial] https://www.kancloud.cn/aceld/zinx │
└───────────────────────────────────────────────────┘
[Zinx] Version: V0.11, MaxConn: 3, MaxPacketSize: 4096
Add api msgId = 0
Add api msgId = 1
[START] Server name: zinx server Demo,listenner at IP: 127.0.0.1, Port 8999 is starting
Worker ID = 0 is started.
Worker ID = 1 is started.
Worker ID = 2 is started.
Worker ID = 3 is started.
Worker ID = 4 is started.
Worker ID = 7 is started.
Worker ID = 6 is started.
Worker ID = 8 is started.
Worker ID = 9 is started.
Worker ID = 5 is started.
start Zinx server zinx server Demo succ, now listenning...
...
$ cd example/zinx_client
$ ./client
==> Test Router:[Ping] Recv Msg: ID= 2 , len= 21 , data= DoConnection BEGIN... ==> Test Router:[Ping] Recv Msg: ID= 0 , len= 18 , data= ping...ping...ping
==> Test Router:[Ping] Recv Msg: ID= 0 , len= 18 , data= ping...ping...ping
==> Test Router:[Ping] Recv Msg: ID= 0 , len= 18 , data= ping...ping...ping
...
t
In the server application developed based on Zinx framework, the main function steps are relatively simple and only need 3 steps at most.
func main() {
//1 Create the server object
s := znet.NewServer()
//2 Configure user-defined routes and services
s.AddRouter(0, &PingRouter{})
//3 Start the service
s.Serve()
}
The custom route and service configuration methods are as follows:
import (
"fmt"
"github.com/aceld/zinx/ziface"
"github.com/aceld/zinx/znet"
)
//ping test custom route
type PingRouter struct {
znet.BaseRouter
}
//Ping Handle
func (this *PingRouter) Handle(request ziface.IRequest) {
//Read the data from the client first
fmt.Println("recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
//To go back to write "ping...ping...ping"
err := request.GetConnection().SendBuffMsg(0, []byte("ping...ping...ping"))
if err != nil {
fmt.Println(err)
}
}
Zinx's message packet format processing uses [MsgLength]|[MsgID]|[Data]
.
package main
import (
"fmt"
"io"
"net"
"time"
"github.com/aceld/zinx/znet"
)
/*
Simulation Client
*/
func main() {
fmt.Println("Client Test ... start")
//A test request is made after 3 seconds, giving the server a chance to start the service
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-- {
//Send a packet 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
}
//Read the head part of the stream first
headData := make([]byte, dp.GetHeadLen())
_, err = io.ReadFull(conn, headData) //ReadFull 会把msg填充满为止
if err != nil {
fmt.Println("read head error")
break
}
//Unpack the headData byte stream into MSG
msgHead, err := dp.Unpack(headData)
if err != nil {
fmt.Println("server unpack err:", err)
return
}
if msgHead.GetDataLen() > 0 {
//msg has data data, which needs to be read again
msg := msgHead.(*znet.Message)
msg.Data = make([]byte, msg.GetDataLen())
//Read the byte stream from the IO according to dataLen
_, 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)
}
}
{
"Name":"zinx v-0.10 demoApp",
"Host":"127.0.0.1",
"TcpPort":7777,
"MaxConn":3,
"WorkerPoolSize":10,
"LogDir": "./mylog",
"LogFile":"zinx.log"
}
Name
:Server Application Name
Host
:Server IP
TcpPort
:Server listening port
MaxConn
:Maximum number of client links allowed
WorkerPoolSize
:Maximum number of working Goroutines in the work task pool
LogDir
: Log folder
LogFile
: Log file name (if not provided, log information is printed to Stderr)
func NewServer () ziface.IServer
Create a Zinx server object that serves as the primary hub for the current server application, including the following functions:
func (s *Server) Start()
func (s *Server) Stop()
func (s *Server) Serve()
func (s *Server) AddRouter (msgId uint32, router ziface.IRouter)
func (s *Server) SetOnConnStart(hookFunc func (ziface.IConnection))
func (s *Server) SetOnConnStop(hookFunc func (ziface.IConnection))
//When you implement Router, you embed the base class and then override the methods of the base class as needed.
type BaseRouter struct {}
//The BaseRouter's methods are null because some Router does not want to
//have PreHandle or PostHandle.
//The Router inherits all BaseRouter's methods because PreHandle and PostHandle can be instantiated
//without implementing them
func (br *BaseRouter)PreHandle(req ziface.IRequest){}
func (br *BaseRouter)Handle(req ziface.IRequest){}
func (br *BaseRouter)PostHandle(req ziface.IRequest){}
func (c *Connection) GetTCPConnection() *net.TCPConn
func (c *Connection) GetConnID() uint32
func (c *Connection) RemoteAddr() net.Addr
func (c *Connection) SendMsg(msgId uint32, data []byte) error
func (c *Connection) SendBuffMsg(msgId uint32, data []byte) error
//Setting connection attributes
func (c *Connection) SetProperty(key string, value interface{})
//Getting connection attributes
func (c *Connection) GetProperty(key string) (interface{}, error)
//remove connection attributes
func (c *Connection) RemoveProperty(key string)
Thanks to all the developers who contributed to Zinx!
name
:Aceld(刘丹冰)
mail
:
danbing.at@gmail.com
github
:
https://github.com/aceld
original work
:
https://www.yuque.com/aceld
WeChat Public Account | QQ Group | |
---|---|---|
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。