Serialization and deserialization methods of shared socket packet
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 []).
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
- Background of this paper
- General operation
- Paper operation
- 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:
- C + + server
- Android client
- IOS client
- 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