Golang Binary Protocol Interface mapping

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

When writing server programs, especially business-to-service (such as game servers), often encounter many client protocols, if the HTTP service, then define the processing interface, the rest to the Web server. But the binary protocol is not so convenient.

The usual custom binary protocol rules are fixed-length message headers + variable length message bodies, with fields such as message length, message ID, and so on in the message header. (based on TCP streaming protocol), after the server receives the client message, it first reads the message header, resolves the message length, and obtains the binary data of the complete message body by the specified length.

When writing specific business logic, you need to face the raw data obtained from the network layer, how to map to the memory data structure and invoke the corresponding processing interface problem. The previous binary message body format is various, we all have their own approach, here in Protobuf as an example, the building server side received the original data, through the message ID map to generate the corresponding PROTOBUF structure, and call the processing interface.

Golang has a reflect package that can reflect the type and dynamically generate the corresponding structure by registering the PROTOBUF message structure with the interface type and message ID into a custom map, preserving the type of struct in the map, as follows:

type MessageHandler func(msgid uint16, msg interface{})type MessageInfo struct {    msgType    reflect.Type    msgHandler MessageHandler}var (    msg_map = make(map[uint16]MessageInfo))func RegisterMessage(msgid uint16, msg interface{}, handler MessageHandler) {    var info MessageInfo    info.msgType = reflect.TypeOf(msg.(proto.Message))    info.msgHandler = handler    msg_map[msgid] = info}

After acquiring the original binary protocol data from the underlying network, the corresponding type information is found in the map by the message ID and the structure type is dynamically created to parse the binary data, as follows:

func HandleRawData(msgid uint16, data []byte) error {    if info, ok := msg_map[msgid]; ok {        msg := reflect.New(info.msgType.Elem()).Interface()        err := proto.Unmarshal(data, msg.(proto.Message))        if err != nil {            return err        }        info.msgHandler(msgid, msg)        return err    }    return errors.New("not found msgid")}

This takes advantage of the reflect reflection mechanism, dynamically acquires the type and creates the PROTOBUF structure, and then passes the Proto. The Umarshal interface parses the binary message body and finally calls Msghandler for processing. Here Msghandler is a message processing interface type, each message is defined by the specification of its own processing function, at the time of program startup, the message, PROTOBUF structure and processing functions are unified registration, as follows:

const (    MsgID_Test1 = iota    MsgID_Test2)func MessageHandler_Test1(msgid uint16, msg interface{}) {    p := msg.(*pb.MsgTest1)    fmt.Println("message handler msgid:", msgid, " body:", p)}func MessageHandler_Test2(msgid uint16, msg interface{}) {    p := msg.(*pb.MsgTest2)    fmt.Println("message handler msgid:", msgid, " body:", p)}func RegistMsg() {    RegisterMessage(MsgID_Test1, &pb.MsgTest1{}, MessageHandler_Test1)    RegisterMessage(MsgID_Test2, &pb.MsgTest2{}, MessageHandler_Test2)}

The registered function here uses the pointer type of the PROTOBUF message body, so when the reflect type is reflected, it is necessary to get the base type of the pointer through the type's Elem () function, and then dynamically create the type.

After this processing, each new protocol only need to add a new line in the REGISTMSG function, do not need each protocol to deal with the binary protocol conversion, structure mapping and other repetitive and complex things.

Code in: Https://github.com/pertgame/gmsg-framework

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.