使用GoLang开发游戏服务器(六)

消息管理模块开发

之前的框架只能处理一种类型的消息,只有一个路由,但是业务中往往有很多不同类型的消息要处理,所以需要框架能处理各种消息,并且让用户在外部定义

  • 新增IMessageHandler.go接口文件
type IMessageHandler interface {
	DoMessageHandler(request IRequest)
	AddRouter(msgID uint32, router IRouter)
}
  • 新增MessageHandler.go结构体文件
type MessageHandler struct {
	Apis map[uint32]ziface.IRouter
}

func NewMessageHandler() *MessageHandler {
	apis := make(map[uint32]ziface.IRouter)
	return &MessageHandler{Apis: apis}
}

func (m *MessageHandler) DoMessageHandler(request ziface.IRequest) {
	if router, ok := m.Apis[request.GetMsgID()]; ok {
		router.PreHandle(request)
		router.Handle(request)
		router.PostHandle(request)
	} else {
		fmt.Println("Not Have MsgID:", request.GetMsgID())
	}
}

func (m *MessageHandler) AddRouter(msgID uint32, router ziface.IRouter) {
	if _, ok := m.Apis[msgID]; ok {
		panic("Error MsgID Have Not Again Add MsgID:" + string(msgID))
	}
	m.Apis[msgID] = router
	fmt.Println("Add Router success MsgID:", msgID)
}

集成消息管理模块到框架中

替换Server中原本的单一路由变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
替换Connection中的单一路由变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

测试消息管理模块

  • 项目结构
    在这里插入图片描述
  • 服务端
    新增一个路由来处理新的Msg
type PingRouter struct {
	znet.BaseRouter
}

func (p *PingRouter) Handle(request ziface.IRequest) {
	fmt.Println("服务器接收到客户端的消息,MsgID:", request.GetMsgID(), "MsgData:", string(request.GetData()))
	err := request.GetConnection().SendMsg(200, []byte("ping...ping...ping..."))
	if err != nil {
		fmt.Println("Handle Error:", err)
		return
	}
}

type HelloRouter struct {
	znet.BaseRouter
}

func (h *HelloRouter) Handle(request ziface.IRequest) {
	fmt.Println("服务器接收到客户端的消息,MsgID:", request.GetMsgID(), "MsgData:", string(request.GetData()))
	err := request.GetConnection().SendMsg(201, []byte("Hello!!!"))
	if err != nil {
		fmt.Println("Handle Error:", err)
		return
	}
}

func main() {
	s := znet.NewServer("[zinxV0.5]ServerApp")
	s.AddRouter(1, &PingRouter{})
	s.AddRouter(2, &HelloRouter{})
	s.Serve()
}
  • 客户端
    发送两种不同的消息
func main() {
	fmt.Println("Client Start...")
	time.Sleep(time.Second)
	conn, err := net.Dial("tcp", "127.0.0.1:8080")
	if err != nil {
		fmt.Println("Client Start Error", err)
		return
	}

	//创建子Goroutine去读取数据
	go func() {
		for true {
			dp := znet.NewDataPack()
			headData := make([]byte, dp.GetHeadLength())
			_, err := io.ReadFull(conn, headData)
			if err != nil {
				fmt.Println(err)
				return
			}

			msg, err := dp.UnPack(headData)
			if err != nil {
				fmt.Println(err)
				return
			}
			var buffer []byte
			if msg.GetMsgLength() <= 0 {
				return
			}
			buffer = make([]byte, msg.GetMsgLength())
			_, err = io.ReadFull(conn, buffer)
			if err != nil {
				fmt.Println(err)
				return
			}
			msg.SetMsgData(buffer)
			fmt.Println("接收服务器的消息,MsgID:", msg.GetMsgID(), "MsgData:", string(msg.GetMsgData()))
		}
	}()

	//让主Goroutine阻塞,去写数据
	for true {
		dp := znet.NewDataPack()
		buffer1, err := dp.Pack(znet.NewMessage(1, []byte("你好啊服务器!!! 我是消息1")))
		if err != nil {
			fmt.Println(err)
			return
		}
		_, err = conn.Write(buffer1)
		if err != nil {
			fmt.Println(err)
			return
		}
		//新增的消息
		buffer2, err := dp.Pack(znet.NewMessage(2, []byte("你好啊服务器!!! 我是消息2")))
		if err != nil {
			fmt.Println(err)
			return
		}
		_, err = conn.Write(buffer2)
		if err != nil {
			fmt.Println(err)
			return
		}
		time.Sleep(time.Second)
	}
}