networkComms.net2.3.1开源版本,基于gpl V3协议。因为不能公开3.x版本的源码,所以基于此版本进行学习。3.X版本进行了诸多改进和Bug修复,使用方法上两者相差不大。
下面的代码请遵循 Gplv3协议
来自英国剑桥的c#网络通讯框架 英文网站www.networkcomms.net 开源版本networkcomms2.3.1 可以进入此页面下载 networkcomms网络通讯框架学习
Packet类。
使用NetworkComms.net 进行网络通信时,比如要从客户端把一个类发送到服务器,或者从服务器把类发送到客户端。在Networkcomms.Net内部都会把类转化为Packet. (不需要我们操作)
/// <summary>
/// 数据包数据的包装器
/// </summary>
public class Packet : IDisposable
{
//数据包的包头部分
PacketHeader packetHeader;
//数据包中的数据部分
StreamSendWrapper packetData;
/// <summary>
/// 创建一个新的数据包
/// </summary>
/// <param name="packetTypeStr">请求类型,这个请求类型是一个字符串,比如提交数据到服务器,请求类型可以写成"someData",然后在服务器端对请求类型"someData"进行相应的处理操作。这个类型只要客户端与服务器能对应上就行,随便命名</param>
/// <param name="packetObject">要发送的数据类,一般是契约类</param>
/// <param name="options">收发参数--创建数据包时需使用</param>
public Packet(string packetTypeStr, object packetObject, SendReceiveOptions options)
{
Constructor(packetTypeStr, null, packetObject, options);
}
/// <summary>
/// 创建一个新数据包
/// </summary>
/// <param name="sendingPacketTypeStr">请求类型,这个请求类型是一个字符串,比如登陆操作,请求类型可以写成"login",然后在服务器端对请求类型"login"进行相应的处理操作,返回登陆结果。这个类型只要客户端与服务器能对应上就行</param>
/// <param name="requestReturnPacketTypeStr">返回类型 有的情况 比如登陆操作 需要服务器返回登陆结果 就需要设定返回类型,如果只是客户端提交数据,而不需要知道服务器的处理结果,则不用设定此项 </param>
/// <param name="packetObject">要发送的数据类,一般是契约类</param>
/// <param name="options">收发参数--创建数据包时需使用</param>
public Packet(string sendingPacketTypeStr, string requestReturnPacketTypeStr, object packetObject, SendReceiveOptions options)
{
Constructor(sendingPacketTypeStr, requestReturnPacketTypeStr, packetObject, options);
}
//创建器
private void Constructor(string sendingPacketTypeStr, string requestReturnPacketTypeStr, object packetObject, SendReceiveOptions options)
{
if (sendingPacketTypeStr == null || sendingPacketTypeStr == "") throw new ArgumentNullException("sendingPacketTypeStr", "The provided string can not be null or zero length.");
if (options == null) throw new ArgumentNullException("options", "The provided SendReceiveOptions cannot be null.");
if (packetObject == null)
this.packetData = new StreamSendWrapper(new ThreadSafeStream(new MemoryStream(new byte[0], 0, 0, false, true), true));
else
{
if (options.DataSerializer == null) throw new ArgumentNullException("options", "The provided SendReceiveOptions.DataSerializer cannot be null.");
this.packetData = options.DataSerializer.SerialiseDataObject(packetObject, options.DataProcessors, options.Options);
}
//We only calculate the checkSum if we are going to use it
string hashStr = null;
if (NetworkComms.EnablePacketCheckSumValidation)
hashStr = NetworkComms.MD5Bytes(packetData.ThreadSafeStream.ToArray(packetData.Start, packetData.Length));
//创建数据包包头部分
this.packetHeader = new PacketHeader(sendingPacketTypeStr, packetData.Length, requestReturnPacketTypeStr,
options.Options.ContainsKey("ReceiveConfirmationRequired"),
hashStr,
options.Options.ContainsKey("IncludePacketConstructionTime"));
//Add an identifier specifying the serializers and processors we have used
this.packetHeader.SetOption(PacketHeaderLongItems.SerializerProcessors, DPSManager.CreateSerializerDataProcessorIdentifier(options.DataSerializer, options.DataProcessors));
if (NetworkComms.LoggingEnabled) NetworkComms.Logger.Trace(" ... creating comms packet. PacketObject data size is " + packetData.Length.ToString() + " bytes");
}
/// <summary>
/// 数据包的包头 PacketHeader类中包含数据包的长度信息
/// </summary>
public PacketHeader PacketHeader
{
get { return packetHeader; }
}
/// <summary>
/// 数据包的数据部分
/// </summary>
public StreamSendWrapper PacketData
{
get { return packetData; }
}
/// <summary>
/// 把数据包包头序列化为二进制数据
/// </summary>
/// <returns>The serialised header as byte[]</returns>
public byte[] SerialiseHeader(SendReceiveOptions options)
{
if (options == null) throw new ArgumentNullException("options", "Provided SendReceiveOptions cannot be null.");
//We need to start of by serialising the header
byte[] serialisedHeader;
using(StreamSendWrapper sendWrapper = options.DataSerializer.SerialiseDataObject(packetHeader, options.DataProcessors, null))
serialisedHeader = sendWrapper.ThreadSafeStream.ToArray(1);
if (serialisedHeader.Length - 1 > byte.MaxValue)
throw new SerialisationException("Unable to send packet as header size is larger than Byte.MaxValue. Try reducing the length of provided packetTypeStr or turning off checkSum validation.");
//The first byte now specifies the header size (allows for variable header size)
//数据包包头的第一个字节为数据包包头的长度
//服务器接收到数据后,第一个字节的内容是数据包包头的长度,服务器根据这个包头的长度解析出数据包包头,然后在根据数据包包头中的数据长度,解析出数据
serialisedHeader[0] = (byte)(serialisedHeader.Length - 1);
if (serialisedHeader == null)
throw new SerialisationException("Serialised header bytes should never be null.");
return serialisedHeader;
}
/// <summary>
/// Dispose of internal resources
/// </summary>
public void Dispose()
{
packetData.Dispose();
}
}
【开源下载】基于TCP网络通信的即时聊天系统(IM系统)(c#源码)
[源码下载]Demo2.模拟简单登陆-效果图 基于networkcomms2.3.1
[源码下载]Demo1 客户端从服务器获取信息(基于networkcomms2.3.1)
【开源下载】基于TCP网络通信的自动升级程序c#源码