Serialization and deserialization methods of shared socket packets

Time:2021-12-13

Serialization and deserialization methods of shared socket packets

To be brief, this article does not cover socket connection and data reception, but only introduces the encapsulation of serialization and deserialization methods of data packets (byte []).

Contents of this article

  1. Background of this paper
  2. General operation
  3. Paper operation
  4. summary

1. Background

Often do C / s, the communication between the client and the server is basically TCP / UDP communication, and the socket can fly.

For example, we have a system, which is divided into several system sub module processes:

  1. C + + server
  2. Android client
  3. IOS client
  4. WPF desktop management
    ……

Several modules communicate through TCP or UDP. Packet parsing and assembly are routine operations. We define the packet format as follows:

A packet contains a header and a body, which are defined as follows:

Baotou

Serial number Field name data type remarks
1 Message ID int Used to identify whether the packet is legal
2 name string Current message name, used to identify the packet type
3 Version number int The current message version number, which allows multiple versions of messages in the program for version iteration

It contains three fields: message ID, name and version number. It uniquely determines the message object.

Inclusion

Serial number Field name data type remarks
1 Field 1 data type Field 1
2 Field 2 data type Field 2

The package body directly defines field information, just like defining class attributes.

In addition, the data types in the header and body are defined as follows:

Packet field type definition

Serial number data type remarks
1 int 4-byte integer value
2 string Composition format: String actual value byte length (2 bytes) + string actual value byte
3 char Single byte value
4 list Composition format: 4 bytes list length + list actual data value byte
5 Dictionaries Ibid., see the source code for details

Similar to other data types, complex data types use a value of 4 bytes, byte length + actual value byte.

Give a test packet

Serial number Field name data type remarks
1 Message ID int Value: 0x4a534604
2 Message name string Three country information, value: “threecountries”
3 Version number int Value: 1
4 number int Give the Three Kingdoms a number, value: 1
5 Country name string Value: “Shu state”
6 emperor string Value: “Liu Bei”
7 Number of generals int 5
8 General 1 No int Value: 1
9 General 1 name string Value: “Zhang Fei”
10 General 1 remarks string Value: “three board axe”
11 General 2 No int Value: 2
12 General 2 name string Value: “Guan Yu”
13 General 2 remarks string Value: “Qinglong Yanyue Sabre”
14 General 3 No int Value: 3
15 General 3 name string Value: “Zhao Yun”
16 General 3 remarks string Value: “very fierce”
17 General 4 No int Value: 4
18 General 4 name string Value: “Ma Chao”
19 General 4 remarks string Value: “strong”
20 General 5 No int Value: 5
21 General 5 name string Value: “Huang Zhong”
22 General 5 remarks string Value: “old and strong”

Generally speaking:

  • The first three fields are the package body: used to identify the entire data package for easy package body analysis;
  • The latter package is simply a brief introduction to the national information of the three countries. The first three fields are the basic information of a country in the three countries: number, country name and emperor, followed by the information list of the country’s senior general. Each senior general has number, name, remarks, etc.

Define data objects

According to the package definition, we can quickly define classes for use, whether you are C + + or Java. The following is the corresponding class I wrote in c# for serialization and deserialization:

/// 
///Three Kingdoms
/// 
public class ThreeCountries
{
    /// 
    ///Get or set ID
    /// 
    public int ID { get; set; }

    /// 
    ///Gets or sets the country name
    /// 
    public string Name { get; set; }

    /// 
    ///Gets or sets the value
    /// 
    public string Emperor { get; set; }

    /// 
    ///Get or set the selected course list
    /// 
    public List Courses { get; set; }

    public override string ToString()
    {
        Return $"one of the Three Kingdoms {ID}: {name} emperor {emperor}, with {courses. Count} generals";
    }
}

/// 
///Three Kingdoms名将
/// 
public class FamousGeneral
{
    /// 
    ///Gets or sets the number
    /// 
    public int ID { get; set; }

    /// 
    ///Gets or sets the name
    /// 
    public string Name { get; set; }

    /// 
    ///Gets or sets the description
    /// 
    public string Memo { get; set; }

    public override string ToString()
    {
        return $"{ID}:{Name}=>{Memo}";
    }
}

How do you serialize and deserialize the packets given above? The converted data is as follows, which will be discussed in the next section

ThreeCountries shuKingdom = new ThreeCountries
{
    ID = 1,
    Name = "Shu",
    Employee = "Liu Bei",
    Courses = new System.Collections.Generic.List
    {
        New famousgeneral {id = 1, name = "Zhang Fei", memo = "three board axe"},
        New famousgeneral {id = 2, name = "Guan Yu", memo = "Qinglong Yanyue Sabre"},
        New famousgeneral {id = 3, name = "Zhao Yun", memo = "fierce"},
        New famousgeneral {id = 3, name = "Ma Chao", memo = "Qiang"},
        New famousgeneral {id = 3, name = "Huang Zhong", memo = "old and strong"},
    }
};

2. General operation

serialize

The code is too cumbersome. I’ll write an informal pseudo code

Define a byte array;
1、 Write packet header
1. Write 4-byte message ID: 0x4a534604
Calculate the length of the message object name string "threecountries" and convert the string to a byte array
2. Write the byte array length of 2 bytes, and write the actual byte array value
3. Write a 4-byte message version number
2、 Write packet body
4. Number of 4 bytes written
Cycle each general information and write it in sequence
5. Write general1 number
6. Write general1 name
7. Write 1 remarks
8. Write general2 number
9. Write general 3 name
10. Write 4 remarks
... Write vomit, ellipsis

Deserialization

I don't want to write. I'm tired

General operation

Define a serialization interface, and each network object implements its serialization and deserialization interfaces

public interface ISerializeInterface
{
  byte[] Serialize(T t);
  T Deserialize(byte[] arr);
}

public class ThreeCountries : ISerializeInterface
{
  public byte[] Serialize(T t)
  {
    //Write the above serialization code here
  }
  
  T Deserialize(byte[] arr)
  {
    //Write the above deserialization code here. I'm sorry I didn't write it
  }
}

3. Operation of this paper

After writing the demo for a long time, the article may be a little watery. I guess readers won’t look at the code carefully and go directly to the GitHub check project. Ha ha.

Let me talk briefly. The implementation is very simple. Define some features. The code file in the red box below:

序列化特性及帮助类

It is easy to use. Add features to the above data classes without much change. See the following code:

/// 
///Three Kingdoms
/// 
[NetObject(Name = "ThreeCountries", Version = 1)]
public class ThreeCountries
{
    /// 
    ///Get or set ID
    /// 
    [NetObjectProperty(ID = 1)]
    public int ID { get; set; }

    /// 
    ///Gets or sets the country name
    /// 
    [NetObjectProperty(ID = 2)]
    public string Name { get; set; }

    /// 
    ///Gets or sets the value
    /// 
    [NetObjectProperty(ID = 3)]
    public string Emperor { get; set; }

    /// 
    ///Get or set the selected course list
    /// 
    [NetObjectProperty(ID = 4)]
    public List Courses { get; set; }

    public static NetObjectAttribute CurrentObject = null;

    static ThreeCountries()
    {
        CurrentObject = NetObjectSerializeHelper.GetAttribute(default(ThreeCountries));
    }

    public override string ToString()
    {
        Return $"one of the Three Kingdoms {ID}: {name} emperor {emperor}, with {courses. Count} generals";
    }
}

/// 
///Three Kingdoms名将
/// 
public class FamousGeneral
{
    /// 
    ///Gets or sets the number
    /// 
    [NetObjectProperty(ID = 1)]
    public int ID { get; set; }

    /// 
    ///Gets or sets the name
    /// 
    [NetObjectProperty(ID = 2)]
    public string Name { get; set; }

    /// 
    ///Gets or sets the description
    /// 
    [NetObjectProperty(ID = 3)]
    public string Memo { get; set; }

    public override string ToString()
    {
        return $"{ID}:{Name}=>{Memo}";
    }
}

If you look carefully, only in the outer class(ThreeCountries)PlusNetObjectFeatures, and attributes are addedNetObjectPropertyAttribute, respectively identifying the message name, version number and the serialization and deserialization order of each attribute, and the sub objects used in the classCoursesAttribute, you only need to add attribute features, as above.

Add the unit test below, and the test passes:

单元测试通过

4. Summary

With this set of code (demo, it has changed, but it is almost the same), I have completed several similar projects. Every time my colleagues in C + + and Java come to me for data communication joint debugging and testing problems, I say:

“First, see if there is any problem with the serialization and deserialization code of your own data packet. I won’t have a problem. It’s completely converted according to the data packet format.”

It was still noisy at the beginning. After locating the problems several times later, they didn’t come to me for similar problems. They were laughing.

Source code: see open source projectTerminalMACS

Original link:https://dotnet9.com/16583.html

Welcome to my WeChat official account: Dotnet9

Dotnet9微信公众号

Recommended Today

Video processing to make video live

Web developers have always wanted to use audio and video in the web, but earlier, traditional web technologies could not embed audio and video in the web, so some patented technologies such as flash and Silverlight became very popular in dealing with these contents. These technologies can work normally, but they have a series of […]