接上一篇《基于.NET技术的监控系统应用分析》中所描述的数据通信协议设计,我们来看一下在C#中是怎么对自定义协议进行封包的?我们知道基于流的数据协议的特点:发送和接收到的数据都是连续的流。每次网络I/O操作的流长度不确定,也就是无法知道每次接收到的数据是一个完整的数据包。同样,主机发送一个数据包也会根据网络的实际情况执行若干次。所以我们对这类消息的编解码过程需要进行一个统一的封装。
重新回顾一下每个消息的结构:消息头 + 消息体。每次先发送出去的是消息头,然后是消息体。消息头里描述了这个数据包的类型,长度,序列号等信息。消息头的长度是固定的,消息体的长度是根据每个消息类型会有所的区别。
消息头的定义:
字段 | 长度(字节) | 类型 | 说明 |
Length | 4 | Int | 消息的总长度(字节) |
Command ID | 4 | Int | 命令ID |
NodeID | 4 | Int | 结点ID |
TimeID | 4 | Int | 时间戳 |
SequenceID | 4 | Int | 递增序列号 |
对应的封装代码:
Head
1
using System;
2
using MonitorLib.Utility;
3
4
namespace MonitorLib.Protocol
5![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
6![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
7
/// 消息头
8
/// </summary>
9
[Serializable]
10
public class Head
11![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
12
private byte[] initValue = new byte[Head.HeaderLength];
13
14
public Head(Command CommandID)
15![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
16
Converter.IntToBytes((uint)CommandID).CopyTo(initValue, 4);
17
}
18
19
public Head(byte[] bs)
20![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
21
uint length = Head.HeaderLength ;
22![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
23
for (int i = 0;i < length;i++)
24![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
25
initValue[i]=bs[i];
26
}
27
}
28![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
29![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
30
public Head(byte[] bs,int baseIndex)
31![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
32
uint length = Head.HeaderLength ;
33![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
34
for (int i = 0; i < length; i++)
35![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
36
initValue[i]=bs[baseIndex+i];
37
}
38
}
39
40![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
41
/// 消息的整个长度
42
/// </summary>
43
public uint Length
44![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
45
get
46![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
47
return (Converter.BytesToUInt(initValue,0));
48
}
49
set
50![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
51
byte[] byt = Converter.IntToBytes(value);
52
for (int i = 0;i < 4;i++)
53![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
54
initValue[i]= byt[i];
55
}
56
}
57
}
58
59![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
60
/// 命令类型
61
/// </summary>
62
public uint CommandID
63![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
64
get
65![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
66
return (Converter.BytesToUInt(initValue, 4));
67
}
68
set
69![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
70
byte[] t=Converter.IntToBytes(value);
71
for (int i = 0; i < 4; i++)
72![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
73
initValue[i + 4] = t[i];
74
}
75
}
76
}
77
78![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
79
/// 源结点号
80
/// </summary>
81
public uint NodeID
82![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
83
get
84![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
85
return (Converter.BytesToUInt(initValue, 8));
86
}
87
set
88![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
89
byte[] t = Converter.IntToBytes(value);
90
for (int i = 0; i < 4; i++)
91![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
92
initValue[i + 8] = t[i];
93
}
94
}
95
}
96![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
97![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
98
/// 时间戳
99
/// </summary>
100
public uint TimeID
101![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
102
get
103![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
104
return (Converter.BytesToUInt(initValue,12));
105
}
106
set
107![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
108
byte[] t = Converter.IntToBytes(value);
109
for (int i = 0; i < 4; i++)
110![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
111
initValue[i + 12] = t[i];
112
}
113
}
114
}
115![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
116![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
117
/// 序列号
118
/// </summary>
119
public uint SequenceID
120![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
121
get
122![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
123
return (Converter.BytesToUInt(initValue,16));
124
}
125
set
126![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
127
byte[] t = Converter.IntToBytes(value);
128
for (int i = 0;i < 4;i++)
129![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
130
initValue[i + 16] = t[i];
131
}
132
}
133
}
134
135
136![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
137
/// 输出字节流
138
/// </summary>
139
/// <returns></returns>
140
public byte[] ToBytes()
141![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
142
return initValue;
143
}
144
145![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
146
/// 从字节流中转换
147
/// </summary>
148
/// <param name="bs"></param>
149
public void FromBytes(byte[] bs)
150![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
151
for (int i = 0; i < Head.HeaderLength; i++)
152![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
153
initValue[i] = bs[i];
154
}
155
}
156
157![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
158
/// 消息头的长度
159
/// </summary>
160
public static uint HeaderLength
161![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
162
get
163![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
164
return (4 + 4 + 12);
165
}
166
}
167
}
168
}
169
上面只是一个消息头,要成为一个完整的消息,一般还必须包含消息体(当然你也可以根据需要仅发送一个消息头的数据,作为特殊用途,例如自定义的心跳包)。举个例子:客户机与服务器连接上后,它通常会发送一个绑定(Bind) 消息给服务器端。例如:验证确认客户端的合法性。那么此时的Bind消息的格式是:
字段 | 长度(字节) | 类型 | 说明 |
HEAD | | | 上面的消息头部 |
loginName | 16 | string | 用户名(固定16位,不足用空格填充) |
LoginPassword | 16 | string | 密码(固定16位,不足用空格填充) |
对应的封装代码:
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
BIND
1
using System;
2
using System.Text;
3
using MonitorLib.Utility;
4![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
5
namespace MonitorLib.Protocol
6![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
7![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
8
/// Bind消息
9
/// </summary>
10
[Serializable]
11
public class Bind : AbstractBase
12![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
13
private string loginName;
14
private string loginPassword;
15![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
16![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
17
/// 初始Bind命令的消息头
18
/// </summary>
19
/// <param name="Sequence">序列号</param>
20
public Bind(Sequence seq)
21![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
22
header = new Head(Command.MOT_BIND);
23
header.NodeID = seq.Node;
24
header.TimeID = seq.Time ;
25
header.SequenceID = seq.Value ;
26
header.Length = Head.HeaderLength + 16 + 16;
27
}
28
29
public Bind(byte[] receive)
30![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
31
initValue = new byte[receive.Length];
32
receive.CopyTo(initValue,0);
33
}
34![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
35![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
36
/// 登录名
37
/// </summary>
38
public string LoginName
39![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
40
get
41![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
42
return Encoding.ASCII.GetString(initValue,20,16);
43
}
44
set
45![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
46
loginName = value;
47
}
48
}
49![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
50![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
51
/// 密码
52
/// </summary>
53
public string LoginPassword
54![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
55
get
56![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
57
return Encoding.ASCII.GetString(initValue,36,16);
58
}
59
set
60![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
61
loginPassword = value;
62
}
63
}
64![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
65![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
66
/// 把消息结构转换成字节数组
67
/// </summary>
68
/// <returns>结果字节数组</returns>
69
public override byte[] ToBytes()
70![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
71
byte[] retValue = new byte[this.header.Length];
72
uint index = 0;
73![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
74
//填充消息头
75
header.ToBytes().CopyTo(retValue,index);
76![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
77
index += Head.HeaderLength;
78
Encoding.ASCII.GetBytes(loginName).CopyTo(retValue,index);
79![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
80
//移位16位, 填充密码
81
index += 16;
82
Encoding.ASCII.GetBytes(loginPassword).CopyTo(retValue,index);
83
return retValue;
84
}
85
}
86![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
87![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
88![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
89
/// Bind应答结构
90
/// </summary>
91
[Serializable]
92
public class Bind_Resp : AbstractBase
93![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
94
private uint result;
95![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
96![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
97
/// 构造函数,把接收的字节数组复制到initValue
98
/// </summary>
99
/// <param name="recBytes">从网络上接收到的字节数组</param>
100
public Bind_Resp(byte[] receive)
101![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
102
initValue = new byte[receive.Length];
103
receive.CopyTo(initValue,0);
104
}
105![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
106
public Bind_Resp(Sequence seq)
107![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
108
header = new Head(Command.MOT_BIND_RESP);
109
header.NodeID = seq.Node;
110
header.TimeID = seq.Time ;
111
header.SequenceID = seq.Value ;
112
header.Length = Head.HeaderLength + 4;
113
}
114![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
115![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
116
/// bind 执行命令是否成功,0-成功。其它:错误码。
117
/// </summary>
118
public uint Result
119![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
120
get
121![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
122
return Convert.ToUInt32(initValue[20].ToString());
123
}
124
set
125![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
126
result = value;
127
}
128
}
129![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
130
public override byte[] ToBytes()
131![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
132
byte[] retValue = new byte[header.Length];
133
header.ToBytes().CopyTo(retValue,0);
134
BitConverter.GetBytes(result).CopyTo(retValue,20);
135
return retValue;
136
}
137
}
138![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
139
}
140
AbstractBase
using System;
using MonitorLib.Utility;
![](https://i-blog.csdnimg.cn/blog_migrate/f0cd6c7f9e7ae96feae062cb48f670f0.gif)
namespace MonitorLib.Protocol
![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0be121fa5b8988fbabbbc526af3b0fc0.gif)
{
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
/**//// <summary>
/// AbstractBase 的摘要说明。
/// </summary>
[Serializable]
public abstract class AbstractBase
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
protected byte[] initValue;
public Head header;
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
public AbstractBase()
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
}
![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
public virtual byte[] ToBytes()
![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
return null;
}
}
}
除了这种协议封装方法外,还有一种直接利用 .NET 的字节流操作类来编解码,例如 ICMP 协议的封包代码:
ICMP
1
public class ICMPHDR
2![](https://i-blog.csdnimg.cn/blog_migrate/34031c708bfe702fe82d01ff5c6593aa.gif)
{
3
private byte mType;
4
public byte Type
5![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
6![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
get
{ return mType; }
7![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
set
{ mType = value; }
8
}
9![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
10
private byte mCode = 0;
11
public byte Code
12![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
13![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
get
{ return mCode; }
14![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
set
{ mCode = value; }
15
}
16![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
17
private ushort mChecksum = 0;
18
public ushort Checksum
19![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
20![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
get
{ return mChecksum; }
21![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
set
{ mChecksum = value; }
22
}
23![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
24
private ushort mID;
25
public ushort ID
26![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
27![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
get
{ return mID; }
28![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
set
{ mID = value; }
29
}
30
31
private ushort mSeq;
32
public ushort Seq
33![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
34![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
get
{ return mSeq; }
35![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
set
{ mSeq = value; }
36
}
37
38
private ulong mtmSend;
39
public ulong tmSend
40![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
41![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
get
{ return mtmSend; }
42![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
set
{ mtmSend = value; }
43
}
44![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
45
private int mnTaskId;
46
public int nTaskId
47![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
48![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
get
{ return mnTaskId; }
49![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
set
{ mnTaskId = value; }
50
}
51![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
52
public void Encode(BinaryWriter writer)
53![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
54
writer.Write(Type);
55
writer.Write(Code);
56
writer.Write((UInt16)Checksum);
57
writer.Write((UInt16)ID);
58
writer.Write((UInt16)Seq);
59
writer.Write((UInt32)tmSend);
60
writer.Write(nTaskId);
61
}
62![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
63
public void Decode(BinaryReader reader)
64![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
65
Type = reader.ReadByte();
66
Code = reader.ReadByte();
67
Checksum = reader.ReadUInt16();
68
ID = reader.ReadUInt16();
69
Seq = reader.ReadUInt16();
70
tmSend = reader.ReadUInt32();
71
nTaskId = reader.ReadInt32();
72
}
73![](https://i-blog.csdnimg.cn/blog_migrate/587e34b10dcf5efbc0859b53470a2db3.gif)
74
public uint Sum()
75![](https://i-blog.csdnimg.cn/blog_migrate/3112b7b6526db5bc83e275260ae60525.gif)
{
76
uint sum = 0;
77
sum += (ushort)(Type + (Code << 8));
78
sum += (ushort)ID;
79
sum += (ushort)Seq;
80
sum += (ushort)tmSend;
81
sum += (ushort)(tmSend >> 16);
82
sum += (ushort)nTaskId;
83
sum += (ushort)(nTaskId >> 16);
84
return sum;
85
}
86
}
以上介绍了用C#是如何对自定义的通信协议封装的过程。 如有不同的处理方法的朋友,欢迎评论,一起探讨一下。