Zinx源代碼
github
https://github.com/aceld/zinx
gitee碼云
https://gitee.com/Aceld/zinx
在線開發(fā)教程
【B站】
zinx視頻教程-Golang輕量級(jí)TCP服務(wù)器框架-適合自學(xué)者
【YouTube】
zinx開發(fā)YouTube中國(guó)版
微信端文檔
【Zinx教程目錄】
完整教程電子版(在線高清)-下載
Zinx框架視頻教程(框架篇)(完整版下載)鏈接在下面正文
Zinx框架視頻教程(應(yīng)用篇)(完整版下載)鏈接在下面正文
Zinx開發(fā)API文檔
Zinx第一章-引言
Zinx第二章-初識(shí)Zinx框架
Zinx第三章-基礎(chǔ)路由模塊
Zinx第四章-全局配置
Zinx第五章-消息封裝
Zinx第六章-多路由模式
Zinx第七章-讀寫分離模型
Zinx第八章-消息隊(duì)列及多任務(wù)
Zinx第九章-鏈接管理
Zinx第十章-連接屬性設(shè)置
【Zinx應(yīng)用案例-MMO多人在線游戲】
(1)案例介紹
(2)AOI興趣點(diǎn)算法
(3)數(shù)據(jù)傳輸協(xié)議protocol buffer
(4)Proto3協(xié)議定義
(5)構(gòu)建項(xiàng)目及用戶上線
(6)世界聊天
(7)上線位置信息同步
(8)移動(dòng)位置與AOI廣播
(9)玩家下線
(10)模擬客戶端AI模塊
1踏枣、寫在前面
? 我們?yōu)槭裁匆鯶inx垢村,Golang目前在服務(wù)器的應(yīng)用框架很多,但是應(yīng)用在游戲領(lǐng)域或者其他長(zhǎng)鏈接的領(lǐng)域的輕量級(jí)企業(yè)框架甚少变抽。
? 設(shè)計(jì)Zinx的目的是我們可以通過(guò)Zinx框架來(lái)了解基于Golang編寫一個(gè)TCP服務(wù)器的整體輪廓,讓更多的Golang愛好者能深入淺出的去學(xué)習(xí)和認(rèn)識(shí)這個(gè)領(lǐng)域俱箱。
? Zinx框架的項(xiàng)目制作采用編碼和學(xué)習(xí)教程同步進(jìn)行陡厘,將開發(fā)的全部遞進(jìn)和迭代思維帶入教程中,而不是一下子給大家一個(gè)非常完整的框架去學(xué)習(xí)扶歪,讓很多人一頭霧水理肺,不知道該如何學(xué)起。
? 教程會(huì)一個(gè)版本一個(gè)版本迭代善镰,每個(gè)版本的添加功能都是微小的妹萨,讓一個(gè)服務(wù)框架小白,循序漸進(jìn)的曲線方式了解服務(wù)器框架的領(lǐng)域炫欺。
? 當(dāng)然乎完,最后希望Zinx會(huì)有更多的人加入,給我們提出寶貴的意見品洛,讓Zinx成為真正的解決企業(yè)的服務(wù)器框架树姨!在此感謝您的關(guān)注摩桶!
二、初探Zinx架構(gòu)
三娃弓、Zinx開發(fā)API文檔
快速開始
server
基于Zinx框架開發(fā)的服務(wù)器應(yīng)用典格,主函數(shù)步驟比較精簡(jiǎn),最多主需要3步即可台丛。
- 創(chuàng)建server句柄
- 配置自定義路由及業(yè)務(wù)
- 啟動(dòng)服務(wù)
func main() {
//1 創(chuàng)建一個(gè)server句柄
s := znet.NewServer()
//2 配置路由
s.AddRouter(0, &PingRouter{})
//3 開啟服務(wù)
s.Serve()
}
其中自定義路由及業(yè)務(wù)配置方式如下:
import (
"fmt"
"zinx/ziface"
"zinx/znet"
)
//ping test 自定義路由
type PingRouter struct {
znet.BaseRouter
}
//Ping Handle
func (this *PingRouter) Handle(request ziface.IRequest) {
//先讀取客戶端的數(shù)據(jù)
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 main
import (
"fmt"
"io"
"net"
"time"
"zinx/znet"
)
/*
模擬客戶端
*/
func main() {
fmt.Println("Client Test ... start")
//3秒之后發(fā)起測(cè)試請(qǐng)求,給服務(wù)端開啟服務(wù)的機(jī)會(huì)
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-- {
//發(fā)封包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 會(huì)把msg填充滿為止
if err != nil {
fmt.Println("read head error")
break
}
//將headData字節(jié)流 拆包到msg中
msgHead, err := dp.Unpack(headData)
if err != nil {
fmt.Println("server unpack err:", err)
return
}
if msgHead.GetDataLen() > 0 {
//msg 是有data數(shù)據(jù)的挽霉,需要再次讀取data數(shù)據(jù)
msg := msgHead.(*znet.Message)
msg.Data = make([]byte, msg.GetDataLen())
//根據(jù)dataLen從io中讀取字節(jié)流
_, 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
:服務(wù)器應(yīng)用名稱
Host
:服務(wù)器IP
TcpPort
:服務(wù)器監(jiān)聽端口
MaxConn
:允許的客戶端鏈接最大數(shù)量
WorkerPoolSize
:工作任務(wù)池最大工作Goroutine數(shù)量
I.服務(wù)器模塊Server
func NewServer () ziface.IServer
創(chuàng)建一個(gè)Zinx服務(wù)器句柄防嗡,該句柄作為當(dāng)前服務(wù)器應(yīng)用程序的主樞紐,包括如下功能:
1) 開啟服務(wù)
func (s *Server) Start()
2) 停止服務(wù)
func (s *Server) Stop()
3) 運(yùn)行服務(wù)
func (s *Server) Serve()
4) 注冊(cè)路由
func (s *Server) AddRouter (msgId uint32, router ziface.IRouter)
5) 注冊(cè)鏈接創(chuàng)建Hook函數(shù)
func (s *Server) SetOnConnStart(hookFunc func (ziface.IConnection))
6) 注冊(cè)鏈接銷毀Hook函數(shù)
func (s *Server) SetOnConnStop(hookFunc func (ziface.IConnection))
II. 路由模塊
//實(shí)現(xiàn)router時(shí)侠坎,先嵌入這個(gè)基類蚁趁,然后根據(jù)需要對(duì)這個(gè)基類的方法進(jìn)行重寫
type BaseRouter struct {}
//這里之所以BaseRouter的方法都為空,
// 是因?yàn)橛械腞outer不希望有PreHandle或PostHandle
// 所以Router全部繼承BaseRouter的好處是实胸,不需要實(shí)現(xiàn)PreHandle和PostHandle也可以實(shí)例化
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) 獲取遠(yuǎn)程客戶端地址信息
func (c *Connection) RemoteAddr() net.Addr
4) 發(fā)送消息
func (c *Connection) SendMsg(msgId uint32, data []byte) error
func (c *Connection) SendBuffMsg(msgId uint32, data []byte) error
5) 鏈接屬性
//設(shè)置鏈接屬性
func (c *Connection) SetProperty(key string, value interface{})
//獲取鏈接屬性
func (c *Connection) GetProperty(key string) (interface{}, error)
//移除鏈接屬性
func (c *Connection) RemoveProperty(key string)
關(guān)于作者:
作者:Aceld(劉丹冰)
mail: danbing.at@gmail.com
github: https://github.com/aceld
原創(chuàng)書籍gitbook: http://legacy.gitbook.com/@aceld
創(chuàng)作不易, 共同學(xué)習(xí)進(jìn)步, 歡迎關(guān)注作者, 回復(fù)"zinx"有好禮
文章推薦
開源軟件作品
(原創(chuàng)開源)Zinx-基于Golang輕量級(jí)服務(wù)器并發(fā)框架[完整版(附教程視頻)]
(原創(chuàng)開源)Lars-基于C++負(fù)載均衡遠(yuǎn)程調(diào)度系統(tǒng)[完整版]
精選文章
使用Golang的interface接口設(shè)計(jì)原則
深入淺出Golang的協(xié)程池設(shè)計(jì)
Go語(yǔ)言構(gòu)建微服務(wù)一站式解決方案
Golang中的局部變量“何時(shí)棧?何時(shí)堆?”
原創(chuàng)聲明:未經(jīng)作者允許請(qǐng)勿轉(zhuǎn)載,或者轉(zhuǎn)載請(qǐng)注明出處!