【Zinx第一章-引言】Golang輕量級併發伺服器框架
【Zinx教程目錄】 Zinx原始碼
【Zinx應用案例-MMO多人線上遊戲】
(9)玩家下線
1、寫在前面
我們為什麼要做Zinx,Golang目前在伺服器的應用框架很多,但是應用在遊戲領域或者其他長連結的領域的輕量級企業框架甚少。
設計Zinx的目的是我們可以通過Zinx框架來了解基於Golang編寫一個TCP伺服器的整體輪廓,讓更多的Golang愛好者能深入淺出的去學習和認識這個領域。
Zinx框架的專案製作採用編碼和學習教程同步進行,將開發的全部遞進和迭代思維帶入教程中,而不是一下子給大家一個非常完整的框架去學習,讓很多人一頭霧水,不知道該如何學起。
教程會一個版本一個版本迭代,每個版本的新增功能都是微小的,讓一個服務框架小白,循序漸進的曲線方式瞭解伺服器框架的領域。
當然,最後希望Zinx會有更多的人加入,給我們提出寶貴的意見,讓Zinx成為真正的解決企業的伺服器框架!在此感謝您的關注!
二、初探Zinx架構
三、Zinx開發API文件
快速開始
server
基於Zinx框架開發的伺服器應用,主函式步驟比較精簡,最多主需要3步即可。
- 建立server控制程式碼
- 配置自定義路由及業務
- 啟動服務
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 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]
的封包格式
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配置檔案
{
"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)
關於作者:
作者:Aceld(劉丹冰)
簡書號:IT無崖子
mail: danbing.at@gmail.com">danbing.at@gmail.com github: https://github.com/aceld 原創書籍gitbook: http://legacy.gitbook.com/@aceld
原創宣告:未經作者允許請勿轉載,或者轉載請註明出處!
相關文章
- 【Zinx第四章-全域性配置】Golang輕量級併發伺服器框架Golang伺服器框架
- 【Zinx第三章-基礎路由模組】Golang輕量級併發伺服器框架路由Golang伺服器框架
- Fastflow——基於golang的輕量級工作流框架ASTGolang框架
- [譯文]greenlet:輕量級併發程式
- Golang web filter 輕量級實現GolangWebFilter
- ColyseusJS 輕量級多人遊戲伺服器開發框架 - 中文手冊(上)JS遊戲伺服器框架
- ColyseusJS 輕量級多人遊戲伺服器開發框架 - 中文手冊(中)JS遊戲伺服器框架
- ColyseusJS 輕量級多人遊戲伺服器開發框架 - 中文手冊(下)JS遊戲伺服器框架
- Flutter路由輕量級框架FRouterFlutter路由框架
- 輕量級orm框架——gzero指南ORM框架
- 輕量級Web框架Flask(二)Web框架Flask
- Solon 1.6.25 釋出,輕量級應用開發框架框架
- Solon 1.6.18 釋出,輕量級應用開發框架框架
- looter——超輕量級爬蟲框架爬蟲框架
- Lite Actor:方舟Actor併發模型的輕量級優化模型優化
- ColyseusJS 輕量級多人遊戲伺服器開發框架 - 中文手冊(系統保障篇)JS遊戲伺服器框架
- 輕量級 Web 框架 Gin 結構分析Web框架
- 輕量級DI框架Guice使用詳解框架GUI
- 【django輕量級框架】django專案部署到阿里雲伺服器流程Django框架阿里伺服器
- 搭建基於springboot輕量級讀寫分離開發框架Spring Boot框架
- java併發筆記之synchronized 偏向鎖 輕量級鎖 重量級鎖證明Java筆記synchronized
- azeroth-event輕量級事件驅動框架事件框架
- 「造個輪子」——cicada(輕量級 WEB 框架)Web框架
- CherryPy :一個輕量級的 Python Web 框架PythonWeb框架
- Spring 5| 輕量級的開源JavaEE框架SpringJava框架
- 輕量級多級選單控制框架程式(C語言)框架C語言
- 輕量級 Java 基礎開發框架,Solon & Solon Cloud 1.5.48 釋出Java框架Cloud
- Solon & Solon Cloud 1.5.62 釋出,輕量級 Java 基礎開發框架CloudJava框架
- 輕量級 Java 基礎開發框架,Solon & Solon Cloud 1.5.40 釋出Java框架Cloud
- 輕鬆檢測Golang併發的資料競爭Golang
- golang併發Golang
- CQRS輕量級框架【CQRSlite】學習使用小記框架
- python輕量級orm框架 peewee常用功能速查PythonORM框架
- SpringBoot接入輕量級分散式日誌框架(GrayLog)Spring Boot分散式框架
- 仿Laravel寫了一個輕量級的框架Laravel框架
- Golang wails2 輕量級跨端桌面解決方案GolangAI跨端
- Nginx初步(反向代理/Web伺服器/輕量級)NginxWeb伺服器
- core_framework —— 基於libev的輕量級lua網路開發框架Framework框架