Communication between different processes requires some identifiers to define the meaning and data format of this communication. These identifiers are often called messages. Next we will discuss how to organize these identifiers and their corresponding data formats.
Traditionally, constants (enumeration or macros) are used to define message numbers, and struct is used to define the data formats of each message. During parsing, the switch-case constant uses the corresponding struct to parse and process the data. This native method will cause various problems: it makes the switch-case processing function very persistent and difficult to maintain. The ing between message numbers and their data format struct is chaotic, which is not conducive to the shunting of new messages. Then the idea of segmentation and message structure inheritance is developed to ease this situation. Today, I am exploring to extend these ideas to make it easier to define and use messages.
When solving the "big" problem, the division and control method can often receive very good results. In the face of the message of the attention, we can segment them in a decisive manner, and then apply a small strategy on the segment: logically, each segment forms a tree structure. Each node of the tree is either a specific message or a segment. Each node has a value and type (core idea). The Node value is unique among the brothers, and the node type is inherited from the parent node. Only segments can have subnodes.
_ Root _
/\
Protocola _ Segmenta _
/| \
_ Segmentaa _ segmentbb _ protocolaa
......
[Root is the root node of the message, segment is the message segment, and protocol is the message number]
The message value and type are in the domain of the parent node. For example, the parameter _ root _: Protocola is used to access the message Protocola. In this way, we prevent naming conflicts. For example, the Team team system agrees to invite messages, and the copy system also agrees to invite messages.
OK. If so many words are spoken, the code is displayed directly:
//////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// /////////////////
Typedef unsigned char prot_type; // Message ID type
// Root message segment.
Namespace msg_root_sg
{
Struct root_dt {prot_type no () {return _ No;} protected: prot_type _ No ;};
Typedef root_dt mydt;
}
// Start to define a segment
// The Name Of The segment to which the belong belongs: the name of the current segment of the segment.
# Define begin_define_segment (belong, segment )\
Namespace MSG _ # Segment # _ SG \
{\
Typedef MSG _ # Belong # _ SG: Segment # _ DT mydt;
// End the definition of a segment
# Define end_define_segment (segment )}
// Declare a segment in the segment Definition
// The value of the segment name value segment (This value must be unique among the parent's direct child)
# Define declear_segment (segment, value )\
Static prot_type const segment = value ;\
Struct segment # _ DT: Public mydt \
{\
Segment # _ DT () {mydt: _ NO = segment ;}\
Prot_type no () {return _ No ;}\
Protected: prot_type _ No ;\
};
// Declare a message in the segment Definition
// Value of the protocol message name (This value must be unique among the parent's direct child)
# Define declear_protocol (protocol, value) Static prot_type const protocol = value;
// Start to define a message out of the definition of the segment
// The protocol message name of the belong Region
# Define begin_define_protocol (belong, protocol )\
Namespace MSG _ # Belong # _ SG \
{\
Struct protocol # _ DT: Public mydt \
{\
Protocol # _ DT () {mydt: _ NO = protocol ;}
// Defines a message after the end of the definition of the segment
// Protocol message name
# Define end_define_protocol (Protocol )};}
// Define a message in the segment Definition
// Value of the protocol message name (This value must be unique among the parent's direct child)
# Define define_protocol (protocol, value )\
Static prot_type const protocol = value ;\
Struct protocol # _ DT: Public mydt \
{Protocol ##_ DT () {mydt: _ NO = protocol ;}};
Begin_define_segment (root, root) // The root node segment is still the root node. The segment name must be root
Declear_segment (chat, 1) // declare the chat segment
Define_protocol (gc_heart_detect, 100) // defines the gc_heart_detect message, which contains no additional data.
End_define_segment (Root)
// Define the chat message segment
Begin_define_segment (root, chat)
Declear_protocol (cs_gmchat, 10) // declare the GM chat message
End_define_segment (CHAT)
// Define GM chat messages
Begin_define_protocol (chat, cs_gmchat)
Char szcontext [128]; // content
Unsigned char bytype; // type
End_define_protocol (cs_gmchat)
//////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// //////////////////////////////////////// /////////////////
# Include <iostream>
# Include <windows. h>
Void Recv (msg_root_sg: root_dt * pdata); // simulates the global message processing function.
Void msgproc_chat (msg_root_sg: chat_dt * pdata); // message function used to process the chat system (simulate a specific message segment)
Int _ tmain (INT argc, _ tchar * argv [])
{
Msg_chat_sg: cs_gmchat_dt data;
Strcpy (data. szcontext, "this a test ");
Data. bytype = 100;
Void * pdata = & data; // After simulating Network Transmission
Recv (msg_root_sg: root_dt *) pdata );
Msg_root_sg: gc_heart_detect_dt detect;
Pdata = & detect; // After simulating Network Transmission
Recv (msg_root_sg: root_dt *) pdata );
System ("pause ");
Return 0;
}
Void Recv (msg_root_sg: root_dt * pdata)
{
Switch (pdata-> NO ())
{
Case msg_root_sg: chat:
Msgproc_chat (msg_root_sg: chat_dt *) pdata );
Break;
Case msg_root_sg: gc_heart_detect:
STD: cout <"MSG: gc_heart_detect" <STD: Endl;
Break;
Default: break;
}
}
// Process the message function of the Chat System
Void msgproc_chat (msg_root_sg: chat_dt * pdata)
{
Switch (pdata-> NO ())
{
Case msg_chat_sg: cs_gmchat:
{
Msg_chat_sg: cs_gmchat_dt * pchat = (msg_chat_sg: cs_gmchat_dt *) pdata;
STD: cout <"MSG: cs_gmchat ";
STD: cout <"chat:" <pchat-> szcontext <"type:" <pchat-> bytype <STD: Endl;
}
Break;
}
}
PS: several projects are summarized step by step and are also used in the project ~ But it may not be perfect!
The layout Seems messy. I copied it directly from my demo, so I am too lazy to copy it to. h/. cpp.