Skip to content

02 Zinx Router

刘丹冰 edited this page May 11, 2023 · 2 revisions

Case Source Code : https://github.com/aceld/zinx-usage/tree/main/zinx_router

1. IRouter

Zinx supports setting different routing and callback business modes for binary message bodies with different MsgID. The interface definition of IRouter is as follows:

package ziface
/* The router interface, where the router is the processing business method customized by the framework user for the link. The IRequest in the router contains the link information of the link and the request data information of the link.*/typeIRouterinterface {
PreHandle(requestIRequest) // The hook method before processing conn businessHandle(requestIRequest) // The method for processing conn businessPostHandle(requestIRequest) // The hook method after processing conn business
}

The overall business invocation chain is PreHandle()-->Handle()-->PostHandle(). Developers can implement specific Router instances and bind routes to Server/Client instances through the AddRouter() method. An example of specific application instance is as follows.

2. Router in Zinx Server

The code directory structure is as follows:

└── router-usage
├── client
│ ├── main.go
│ └── router
│ └── pong.go
├── common
│ └── proto.go
└── server
├── main.go
└── router
└── ping.go

server/main.go

package main
import (
"github.com/aceld/zinx/znet""zinx-usage/zinx_router/router-usage/server/router"
)
const (
MsgIdPing=1
)
funcmain() {
//1 Create a server services:=znet.NewServer()
//2 Configure routess.AddRouter(MsgIdPing, &router.PingRouter{})
//3 Start the services.Serve()
}

common/proto.go

package common
const (
MsgIdPing=1MsgIdPong=2
)

server/router/ping.go

package router
import (
"fmt""github.com/aceld/zinx/ziface""github.com/aceld/zinx/znet""zinx-usage/zinx_router/router-usage/common"
)
// PingRouter MsgIdPing routetypePingRouterstruct {
znet.BaseRouter
}
//Ping Handle method for MsgIdPing routefunc (r*PingRouter) PreHandle(request ziface.IRequest) {
//Read client datafmt.Println("PreHandle: recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
}
//Ping Handle method for MsgIdPing routefunc (r*PingRouter) Handle(request ziface.IRequest) {
//Read client datafmt.Println("Handle: recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
request.GetConnection().SendMsg(common.MsgIdPong, []byte("pong...pong...pong...[FromServer]"))
}
//Ping Handle method for MsgIdPing routefunc (r*PingRouter) PostHandle(request ziface.IRequest) {
//Read client datafmt.Println("PostHandle: recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
}

When the Server receives the MsgIdPing message, it will call the PreHandle, Handle, and PostHandle methods in turn. Among them, Handle sends the MsgIdPong message back to the client.

3. Router in Zinx Client

Clients can also set up message callback routing using the Router. The Client still provides the AddRouter() method. A specific Client example is shown below:

client/main.go

package main
import (
"fmt""github.com/aceld/zinx/ziface""github.com/aceld/zinx/znet""time""zinx-usage/zinx_router/router-usage/client/router""zinx-usage/zinx_router/router-usage/common"
)
// Custom business logic for the clientfuncpingLoop(conn ziface.IConnection) {
for {
err:=conn.SendMsg(common.MsgIdPing, []byte("Ping...Ping...Ping...[FromClient]"))
iferr!=nil {
fmt.Println(err)
break
}
time.Sleep(1*time.Second)
}
}
// Executed when creating a connectionfunconClientStart(conn ziface.IConnection) {
fmt.Println("onClientStart is Called ... ")
gopingLoop(conn)
}
funcmain() {
// Create the Clientclient:=znet.NewClient("127.0.0.1", 8999)
// Set the hook function after the connection is establishedclient.SetOnConnStart(onClientStart)
// Set the message reading routingclient.AddRouter(common.MsgIdPong, &router.PongRouter{})
// Start the clientclient.Start()
// Prevent process exit, wait for interrupt signalselect {}
}

The router for MsgIdPong messages in the Client is defined as follows:

client/router/pong.go

package router
import (
"fmt""github.com/aceld/zinx/ziface""github.com/aceld/zinx/znet"
)
// PongRouter is the router for MsgIdPongtypePongRouterstruct {
znet.BaseRouter
}
// Handle is the router for MsgIdPongfunc (r*PongRouter) Handle(request ziface.IRequest) {
// Read the data from the clientfmt.Println("Handle: recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
}

After starting the Server and the Client in two terminals, the following output is obtained:

Running the Server

 $ go run main.go PreHandle: recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient]
Handle: recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient]
PostHandle: recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient]
PreHandle: recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient]
Handle: recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient]
PostHandle: recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient]
PreHandle: recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient]
Handle: recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient]
PostHandle: recv from client : msgId= 1 , data= Ping...Ping...Ping...[FromClient]
...

Running the Client

$ go run main.go onClientStart is Called ... Handle: recv from client : msgId= 2 , data= pong...pong...pong...[FromServer]
Handle: recv from client : msgId= 2 , data= pong...pong...pong...[FromServer]
Handle: recv from client : msgId= 2 , data= pong...pong...pong...[FromServer]
Handle: recv from client : msgId= 2 , data= pong...pong...pong...[FromServer]
Handle: recv from client : msgId= 2 , data= pong...pong...pong...[FromServer]
...

The above example is the basic routing configuration mode of Zinx.

4. Router Link Jump

In the Router call, Abort() or Goto() can be used in the callback Handler() to terminate or jump to the corresponding callback node.

Abort

Terminate the link. Server-side code in router-goto/server.go:

package main
import (
"fmt""github.com/aceld/zinx/ziface""github.com/aceld/zinx/znet"
)
typeTestRouterstruct {
znet.BaseRouter
}
func (t*TestRouter) PreHandle(req ziface.IRequest) {
fmt.Println("--> Call PreHandle")
}
func (t*TestRouter) Handle(req ziface.IRequest) {
fmt.Println("--> Call Handle")
//Terminate the route link callreq.Abort()
}
func (t*TestRouter) PostHandle(req ziface.IRequest) {
fmt.Println("--> Call PostHandle")
}
funcmain() {
s:=znet.NewServer()
s.AddRouter(1, &TestRouter{})
s.Serve()
}

Client-side code in router-goto/client.go:

package main
import (
"fmt""github.com/aceld/zinx/ziface""github.com/aceld/zinx/znet""time"
)
//Customize client businessfuncpingLoop(conn ziface.IConnection) {
for {
err:=conn.SendMsg(1, []byte("Ping...Ping...Ping...[FromClient]"))
iferr!=nil {
fmt.Println(err)
break
}
time.Sleep(1*time.Second)
}
}
//Execute when creating a connectionfunconClientStart(conn ziface.IConnection) {
fmt.Println("onClientStart is Called ... ")
gopingLoop(conn)
}
funcmain() {
//Create a Clientclient:=znet.NewClient("127.0.0.1", 8999)
//Set the hook function after the connection is establishedclient.SetOnConnStart(onClientStart)
//Start the clientclient.Start()
//Prevent process exit and wait for interrupt signalselect {}
}

Run the server and client, and observe the printed information in the server terminal:

 $ go run server.go --> Call PreHandle
--> Call Handle
--> Call PreHandle
--> Call Handle
--> Call PreHandle
--> Call Handle
--> Call PreHandle
--> Call Handle

The link only executed PreHandle() --> Handle() and terminated without executing PostHandle().

Goto

Note: Be careful, it will cause loop calling Jump to the link, the jump node provides three macros as follows:

znet.PRE_HANDLE
znet.HANDLE
znet.POST_HANDLE

Server-side code:

package main
import (
"fmt""github.com/aceld/zinx/ziface""github.com/aceld/zinx/znet"
)
typeTestRouterstruct {
znet.BaseRouter
}
func (t*TestRouter) PreHandle(req ziface.IRequest) {
fmt.Println("--> Call PreHandle")
//Jumpreq.Goto(znet.POST_HANDLE)
}
func (t*TestRouter) Handle(req ziface.IRequest) {
fmt.Println("--> Call Handle")
}
func (t*TestRouter) PostHandle(req ziface.IRequest) {
fmt.Println("--> Call PostHandle")
}
funcmain() {
s:=znet.NewServer()
s.AddRouter(1, &TestRouter{})
s.Serve()
}

Run the server and client, and observe the print information in the server terminal:

$go run server.go
--> Call PreHandle
--> Call PostHandle
--> Call PreHandle
--> Call PostHandle
--> Call PreHandle
--> Call PostHandle

The result is that it jumps directly from PreHandle() to PostHandle().

Clone this wiki locally