-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
02 Zinx Router
Case Source Code : https://github.com/aceld/zinx-usage/tree/main/zinx_router
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.
*/
type IRouter interface {
PreHandle(request IRequest) // The hook method before processing conn business
Handle(request IRequest) // The method for processing conn business
PostHandle(request IRequest) // 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.
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
)
func main() {
//1 Create a server service
s := znet.NewServer()
//2 Configure routes
s.AddRouter(MsgIdPing, &router.PingRouter{})
//3 Start the service
s.Serve()
}
common/proto.go
package common
const (
MsgIdPing = 1
MsgIdPong = 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 route
type PingRouter struct {
znet.BaseRouter
}
//Ping Handle method for MsgIdPing route
func (r *PingRouter) PreHandle(request ziface.IRequest) {
//Read client data
fmt.Println("PreHandle: recv from client : msgId=", request.GetMsgID(), ", data=", string(request.GetData()))
}
//Ping Handle method for MsgIdPing route
func (r *PingRouter) Handle(request ziface.IRequest) {
//Read client data
fmt.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 route
func (r *PingRouter) PostHandle(request ziface.IRequest) {
//Read client data
fmt.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.
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 client
func pingLoop(conn ziface.IConnection) {
for {
err := conn.SendMsg(common.MsgIdPing, []byte("Ping...Ping...Ping...[FromClient]"))
if err != nil {
fmt.Println(err)
break
}
time.Sleep(1 * time.Second)
}
}
// Executed when creating a connection
func onClientStart(conn ziface.IConnection) {
fmt.Println("onClientStart is Called ... ")
go pingLoop(conn)
}
func main() {
// Create the Client
client := znet.NewClient("127.0.0.1", 8999)
// Set the hook function after the connection is established
client.SetOnConnStart(onClientStart)
// Set the message reading routing
client.AddRouter(common.MsgIdPong, &router.PongRouter{})
// Start the client
client.Start()
// Prevent process exit, wait for interrupt signal
select {}
}
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 MsgIdPong
type PongRouter struct {
znet.BaseRouter
}
// Handle is the router for MsgIdPong
func (r *PongRouter) Handle(request ziface.IRequest) {
// Read the data from the client
fmt.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:
$ 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]
...
$ 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.
In the Router call, Abort()
or Goto()
can be used in the callback Handler()
to terminate or jump to the corresponding callback node.
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"
)
type TestRouter struct {
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 call
req.Abort()
}
func (t *TestRouter) PostHandle(req ziface.IRequest) {
fmt.Println("--> Call PostHandle")
}
func main() {
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 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)
}
}
//Execute when creating a connection
func onClientStart(conn ziface.IConnection) {
fmt.Println("onClientStart is Called ... ")
go pingLoop(conn)
}
func main() {
//Create a Client
client := znet.NewClient("127.0.0.1", 8999)
//Set the hook function after the connection is established
client.SetOnConnStart(onClientStart)
//Start the client
client.Start()
//Prevent process exit and wait for interrupt signal
select {}
}
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()
.
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"
)
type TestRouter struct {
znet.BaseRouter
}
func (t *TestRouter) PreHandle(req ziface.IRequest) {
fmt.Println("--> Call PreHandle")
//Jump
req.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")
}
func main() {
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()
.