http://www.cnblogs.com/wildman/archive/2009/07/06/1517629.html
接上一篇《基于.NET技术的监控系统应用分析》中所描述的数据通信协议设计,我们来看一下在C#中是怎么对自定义协议进行封包的?我们知道基于流的数据协议的特点:发送和接收到的数据都是连续的流。每次网络I/O操作的流长度不确定,也就是无法知道每次接收到的数据是一个完整的数据包。同样,主机发送一个数据包也会根据网络的实际情况执行若干次。所以我们对这类消息的编解码过程需要进行一个统一的封装。
重新回顾一下每个消息的结构:消息头 + 消息体。每次先发送出去的是消息头,然后是消息体。消息头里描述了这个数据包的类型,长度,序列号等信息。消息头的长度是固定的,消息体的长度是根据每个消息类型会有所的区别。
消息头的定义:
|
字段 |
长度(字节) |
类型 |
说明 |
|
Length |
4 |
Int |
消息的总长度(字节) |
|
Command ID |
4 |
Int |
命令ID |
|
NodeID |
4 |
Int |
结点ID |
|
TimeID |
4 |
Int |
时间戳 |
|
SequenceID |
4 |
Int |
递增序列号 |
对应的封装代码:
上面只是一个消息头,要成为一个完整的消息,一般还必须包含消息体(当然你也可以根据需要仅发送一个消息头的数据,作为特殊用途,例如自定义的心跳包)。举个例子:客户机与服务器连接上后,它通常会发送一个绑定(Bind) 消息给服务器端。例如:验证确认客户端的合法性。那么此时的Bind消息的格式是:
|
字段 |
长度(字节) |
类型 |
说明 |
|
HEAD |
|
|
上面的消息头部 |
|
loginName |
16 |
string |
用户名(固定16位,不足用空格填充) |
|
LoginPassword |
16 |
string |
密码(固定16位,不足用空格填充) |
对应的封装代码:
}
}
}
}
除了这种协议封装方法外,还有一种直接利用 .NET 的字节流操作类来编解码,例如 ICMP 协议的封包代码:
以上介绍了用C#是如何对自定义的通信协议封装的过程。 如有不同的处理方法的朋友,欢迎评论,一起探讨一下。