Data transmission protocol of Socket development framework, socket Data Transmission

Source: Internet
Author: User

Data transmission protocol of Socket development framework, socket Data Transmission

In the previous article "Design and Analysis of Socket Development Framework framework", I introduced the overall idea of the entire Socket development framework, summarizes and abstracts the base classes at various levels to achieve reuse and simplified code. This article continues to analyze the important part of the protocol design, and introduces the design of the Message Protocol, as well as the data unpacking and encapsulation, this allows us to make better use of Socket features at a higher level.

1. protocol design ideas

For the encapsulation and unpacking of Socket transmission messages, most Socket applications use the sequential location and byte length method to determine the relevant content. Such a processing method can greatly reduce the data size, however, it is a disaster to analyze complicated protocol content. Developers who have tracked and solved such a Protocol will have a good understanding of the difficulties. Once the Protocol location changes or requires special processing, It is very error-prone, in addition, most code is filled with numerical variables in many locations, which is inconvenient for analysis and understanding. With the development of network technology, sometimes the data to be transmitted is a little larger, and some bandwidth is lost for data transmission. However, it is our goal to increase the efficiency of development programs exponentially. For example, currently, Web APIs are widely used in various devices. Compared with Socket messages, Web APIs are not dominant in data size, but they are well known for their convenience and efficiency.

The characteristics of Web APIs are used to consider the transmission of Socket messages. For the overall content, the Socket application also uses a flexible message format, such as JSON format for data transmission, therefore, we can deliver two parts: Message encapsulation and message unpacking and parsing to a third-party JSON parser. We only need to pay attention to the specific message processing logic, in addition, Protocol extensions, like JSON, can be freely and flexibly. In this instant, the whole world will be quiet.

For the security and integrity of Socket messages, we can use the RSA public key cryptography system for encryption. The Platform sends the RSA public key message of the platform to inform the terminal of its RSA public key. The terminal replies to the RSA public key message of the terminal. In this way, messages of the platform and terminal can be encrypted through its own private key, let the other party decrypt the data based on the received public key. Although the length of the encrypted data will increase a lot, it is also necessary to adopt this method for high security requirements.

For data integrity, the traditional CRC verification code is not very useful, because our data will not be partially lost, and we should pay more attention to whether the data has been tampered, this reminds me of the design of the Public Account API interface, which carries a secure signature encryption string, that is, to encrypt the content in the API with the same rules, then compare whether the two signatures are consistent. However, for Asymmetric encrypted transmission, such data integrity verification is not necessary.

As described above, we can refer to the Web API method and use the JSON format as the content we transmit to facilitate serial numbers and deserialization, in this way, the analysis difficulty and Error Probability of the Socket protocol can be greatly reduced, the Socket development difficulty can be reduced, and the application development speed can be improved. So how should we design this format?

First, we need to define the start and end identifiers for the Socket message. The middle part is the JSON content of the general message. In this way, apart from the start and end signs, the rest of a complete Socket message is a JSON string data.

We are prepared to design the content of the entire JSON string as needed, and it is better to design more generic, so that we can carry more data information.

 

2. Protocol Design Analysis and Evolution

I have designed the following message format, including the delivery user ID, sending user ID, message type, creation time, and a common content field, this common field should be the JSON string of another message entity, so that the entire message format does not need to be changed, but the specific content is different. We call this object class BaseMessage, common fields are as follows.

The Content field above is used to carry specific message data. It transmits different Content according to different message types, these contents are also specific entity classes serialized as JSON strings. For convenience, we also designed the base classes of these classes, that is, the base class BaseEntity of the object class for Socket data transmission.

We can inherit from different request and response messages. To make it easy to convert to the required BaseMessage message, add an MsgType protocol identifier for it, and add the PackData method to convert the object class to a JSON string.

For example, in general, the Request and Response Message objects are inherited from BaseEntity. We can put these two types of message objects in different directories for convenient management.

The following is an example of the inheritance relationship.

The subclass can use the PackData method of the base class and the serial number is a JSON string. The PacketData function is mainly used to assemble the BaseMessage object to be sent. The function code is as follows:

/// <Summary> /// encapsulate the data for sending /// </summary> /// <returns> </returns> public BaseMessage PackData () {BaseMessage info = new BaseMessage () {MsgType = this. msgType, Content = this. serializeObject ()}; return info ;}

Sometimes we need to construct the returned response message based on the request information, because we need to reverse the sender ID and the delivery ID.

/// <Summary> // encapsulate the data for sending (copy part of the request data) /// </summary> /// <returns> </returns> public BaseMessage PackData (BaseMessage request) {BaseMessage info = new BaseMessage () {MsgType = this. msgType, Content = this. serializeObject (), CallbackID = request. callbackID}; if (! String. IsNullOrEmpty (request. ToUserId) {info. ToUserId = request. FromUserId; info. FromUserId = request. ToUserId;} return info ;}

This section describes the data entity object of the login request. It inherits from BaseEntity and specifies the corresponding message type.

/// <Summary> /// the object of the login request message /// </summary> public class AuthRequest: baseEntity {# region field information // <summary> // user account // </summary> public string UserId {get; set ;} /// <summary> /// User Password /// </summary> public string Password {get; set ;} # endregion // <summary> // default constructor // </summary> public AuthRequest () {this. msgType = DataTypeKey. authRequest ;} /// <summary> /// parameterized constructor /// </summary> /// <param name = "userid"> User Account </param> // <param name = "password"> User password </param> public AuthRequest (string userid, string password): this () {this. userId = userid; this. password = password ;}}

In this way, our message content is very simple, so that we can easily transfer and process it.

 

3. receive and send messages

We have introduced some base classes, including Socket client base classes and data receiving base class designs. These packages can provide me with good convenience.

In the above BaseSocketClient, in order to be able to parse Socket messages of different protocols and convert it to the base class object we need, we introduce a parser MessageSplitter here, this class is mainly used to analyze byte data and extract the entire message.

Therefore, we design the BaseSocketClient class definition code as follows.

/// <Summary> /// basic Socket operation class, which provides operations such as connection, disconnection, receipt, and sending. /// </Summary> /// <typeparam name = "TSplitter"> the message parsing class inherited from MessageSplitter </typeparam> public class BaseSocketClient <TSplitter> where TSplitter: messageSplitter, new ()

The MessageSplitter object is used to process low-level protocol parsing. In addition to the protocol header and Protocol tail identifier, the rest is a JSON object, then it needs to convert byte data to the object level according to this rule.

First, you need to split the byte data and add a complete piece of data to the list for subsequent processing.

At the end, we need to extract the cached direct data to a specific object.

RawMessage msg = this.ConvertMessage(MsgBufferCache, from);

The conversion rules are as follows.

 

In this way, after receiving the message, we can use the TSplitter object for parsing, as shown below is the processing of the Socket message.

TSplitter splitter = new TSplitter (); splitter. initParam (this. socket, this. startByte, this. endByte); // specifies the delimiter used to split the splitter. dataReceived + = splitter_DataReceived; // If a complete package is processed, use Event Notification

After receiving and obtaining the direct data object of a message, we can further convert the direct object into a specific message object.

/// <Summary> /// message splitting class receives a message event // </summary> /// <param name = "data"> original message object </param> void splitter_DataReceived (RawMessage data) {export epackcount + = 1; // increase the number of packets received. OnReadRaw (data) ;}/// <summary> /// process the received data, available for subclass overloading // </summary> // <param name = "data"> original message object (including original byte data) </param> protected virtual void OnReadRaw (RawMessage data) {// provides default Package Processing: assume that the entire content is in Json format; // if you need to process a custom message body, you need to override the OnReadMessage method in the subclass. If (data! = Null & data. Buffer! = Null) {var json = EncodingGB2312.GetString (data. Buffer); var msg = JsonTools. DeserializeObject <BaseMessage> (json); OnReadMessage (msg); // overload the subclass }}

 

At a higher layer of data parsing, we can process object-level messages.

For example, after a message is received, it is resolved to an entity class BaseMessage, so we can use the message content of BaseMessage, you can also convert the Content to the corresponding entity class for processing. The following code shows the processing after receiving the object.

Void TextMsgAnswer (BaseMessage message) {var msg = string. format ("message from [{0}]:", message. fromUserId); var request = JsonTools. deserializeObject <TextMsgRequest> (message. content); if (request! = Null) {msg + = string. format ("{0} {1}", request. message, message. createTime. intToDateTime ();} // MessageUtil. showTips (msg); Portal. gc. mainDialog. appendMessage (msg );}

For sending and processing a message, we can give an example. If you need to obtain the online user list after logging on to the client, you can send a request command, then the server needs to return the list information to the terminal according to this command, as shown in the following code.

/// <Summary> /// process the response from the client request user list /// </summary> /// <param name = "data"> specific message object </ param> private void UserListProcess (BaseMessage data) {CommonRequest request = JsonTools. deserializeObject <CommonRequest> (data. content); if (request! = Null) {Log. writeInfo (string. format ("############ \ r \ n {0}", data. serializeObject (); List <CListItem> list = new List <CListItem> (); foreach (ClientOfShop client in Singleton <ShopClientManager>. instance. loginClientList. values) {list. add (new CListItem (client. id, client. id);} UserListResponse response = new UserListResponse (list); Singleton <ShopClientManager>. instance. addSend (data. fromUserId, response. packData (data), true );}}

 

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.