Zinx Framework

repository·master·Indexed 27 days ago

https://github.com/aceld/zinx

A lightweight, concurrent TCP server framework for Golang (version 1.17+) optimized for long-lived connection scenarios such as gaming servers and message forwarding. It provides a simple structure for implementing servers and clients, featuring a worker pool, JSON-based configuration, and routing mechanisms. The framework includes a case study for an MMO game server with AOI-based broadcasting and global chat.

Tokens
6.3K
Snippets
12
Records
32
Agent score
93%

What's inside zinx

  1. Overview of Zinx Framework

    master
    Zinx is a lightweight concurrent server framework based on Golang. It is designed for scenarios requiring high concurrency and long connections, such as message relaying for backend modules, long-connection game servers, and message processing plugins within Web frameworks. The framework aims to provide a simple code structure that allows developers to understand the internal details of a TCP server and easily perform secondary development (DIY) for specific enterprise needs.
  2. MMO Game Case Study Overview

    master

    The zinx_app_demo/mmo_game repository serves as a practical case study for building a server-side application using the Zinx framework. It implements an MMO (Massively Multiplayer Online) game server featuring essential modules such as:

    • AOI (Area Of Interest) based broadcasting: Efficiently managing message distribution based on player proximity.
    • Global Chat: A system for world-wide communication.

    The demo is designed to work with a Unity3D client, which can be found at the following repository: https://github.com/aceld/mmo_game_client

  3. MMO Game Server Example Overview

    master

    The MMO Game case study demonstrates how to build a Massively Multiplayer Online (MMO) game server using the Zinx framework. It includes core game modules such as AOI (Area of Interest) based broadcasting and world chat. This example is designed to work with a Unity3D client.

    MMO Game Client Source Code (for learning purposes): https://github.com/aceld/mmo_game_client

  4. Quickstart: Create a Zinx Server

    master

    To create a server, use znet.NewServer() to initialize the service, AddRouter to map specific message IDs to router implementations (which embed znet.BaseRouter), and Serve() to start the server. The router's Handle method receives an ziface.IRequest containing the message ID and data.

    package main
    
    import (
    	"fmt"
    	"github.com/aceld/zinx/ziface"
    	"github.com/aceld/zinx/znet"
    )
    
    // PingRouter handles messages with MsgId=1
    type PingRouter struct {
    	znet.BaseRouter
    }
    
    // Handle is the routing method for MsgId=1
    func (r *PingRouter) Handle(request ziface.IRequest) {
    	// Read client data
    	fmt.Println("recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
    }
    
    func main() {
    	// 1. Create a server service
    	s := znet.NewServer()
    
    	// 2. Configure router
    	s.AddRouter(1, &PingRouter{})
    
    	// 3. Start service
    	s.Serve()
    }
  5. Quickstart: Create a Zinx Client

    master

    To create a client, use znet.NewClient(host, port). You can use SetOnConnStart to register a hook function that executes when a connection is successfully established. Use conn.SendMsg(msgId, data) to send messages to the server.

    package main
    
    import (
    	"fmt"
    	"github.com/aceld/zinx/ziface"
    	"github.com/aceld/zinx/znet"
    	"time"
    )
    
    // Custom business logic for the client
    func pingLoop(conn ziface.IConnection) {
    	for {
    		err := conn.SendMsg(1, []byte("Ping...Ping...Ping...[FromClient]"))
    		if err != nil {
    			fmt.Println(err)
    			break
    		}
    
    		time.Sleep(1 * time.Second)
    	}
    }
    
    // Hook function called when connection is established
    func onClientStart(conn ziface.IConnection) {
    	fmt.Println("onClientStart is Called ... ")
    	go pingLoop(conn)
    }
    
    func main() {
    	// Create Client
    	client := znet.NewClient("127.0.0.1", 8999)
    
    	// Set hook function for successful connection
    	client.SetOnConnStart(onClientStart)
    
    	// Start client
    	client.Start()
    
    	// Prevent process from exiting
    	select {}
    }
  6. QuickStart: Implement a Zinx Client

    master

    To create a Zinx client:

    1. Use znet.NewClient(host, port) to initialize the client.
    2. Use client.SetOnConnStart(hookFunc) to define a callback function that executes when a connection is successfully established.
    3. Call client.Start() to begin the connection process.
    4. Use conn.SendMsg(msgId, data) within your business logic to send messages to the server.
    package main
    
    import (
    	"fmt"
    	"github.com/aceld/zinx/ziface"
    	"github.com/aceld/zinx/znet"
    	"time"
    )
    
    //Client custom business
    func pingLoop(conn ziface.IConnection) {
    	for {
    		err := conn.SendMsg(1, []byte("Ping...Ping...Ping...[FromClient]"))
    		if err != nil {
    			fmt.Println(err)
    			break
    		}
    
    		time.Sleep(1 * time.Second)
    	}
    }
    
    //Executed when a connection is created
    func onClientStart(conn ziface.IConnection) {
    	fmt.Println("onClientStart is Called ... ")
    	go pingLoop(conn)
    }
    
    func main() {
    	//Create a client client
    	client := znet.NewClient("127.0.0.1", 8999)
    
    	//Set the hook function after the link is successfully established
    	client.SetOnConnStart(onClientStart)
    
    	//start the client
    	client.Start()
    
    	//Prevent the process from exiting, waiting for an interrupt signal
    	select {}
    }
  7. QuickStart: Implement a Zinx Server

    master

    To create a Zinx server, follow these steps:

    1. Define a router struct that embeds znet.BaseRouter.
    2. Implement the Handle(request ziface.IRequest) method to process incoming messages.
    3. In main(), use znet.NewServer() to create the service.
    4. Register your router using s.AddRouter(msgId, routerInstance).
    5. Start the service with s.Serve().
    package main
    
    import (
    	"fmt"
    	"github.com/aceld/zinx/ziface"
    	"github.com/aceld/zinx/znet"
    )
    
    // PingRouter MsgId=1 
    type PingRouter struct {
    	znet.BaseRouter
    }
    
    //Ping Handle MsgId=1
    func (r *PingRouter) Handle(request ziface.IRequest) {
    	//read client data
    	fmt.Println("recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
    }
    
    func main() {
    	//1 Create a server service
    	s := znet.NewServer()
    
    	//2 configure routing
    	s.AddRouter(1, &PingRouter{})
    
    	//3 start service
    	s.Serve()
    }
  8. Access Zinx Tutorials and Documentation

    master

    To learn how to use the Zinx framework for building services, you can access the following resources:

    Documentation

    Online Tutorials

    Video Tutorials

  9. Zinx Learning Resources and Tutorials

    master

    To learn how to use the Zinx framework, you can access various documentation and tutorial formats:

    Documentation

    Text Tutorials

    Video Tutorials

  10. Configure Zinx via JSON

    master

    Zinx can be configured using a JSON file. The following keys are available:

    • Name: Application name.
    • Host: Server IP address.
    • TCPPort: Port the server listens on.
    • MaxConn: Maximum number of allowed client connections.
    • WorkerPoolSize: Maximum number of Goroutines in the worker task pool.
    • LogDir: Directory for log files.
    • LogFile: Name of the log file (if omitted, logs are printed to Stderr).
    • LogSaveDays: Number of days to retain logs.
    • LogCons: Whether to output logs to the console.
    • LogIsolationLevel: Log isolation level (0: All, 1: Hide debug, 2: Hide debug/info, 3: Hide debug/info/warn).
    {
      "Name":"zinx v-0.10 demoApp",
      "Host":"0.0.0.0",
      "TCPPort":9090,
      "MaxConn":3,
      "WorkerPoolSize":10,
      "LogDir": "./mylog",
      "LogFile":"app.log",
      "LogSaveDays":15,
      "LogCons": true,
      "LogIsolationLevel":0
    }