数据包结构
1、数据包由head+body组成,head为明文,body可加密。
因为使用的是TCP协议不需要分段,head为4字节,存储整个数据包长度,加密模式开启时为20字节,后16字节存储IV。收到一个完整的数据包后去掉head部分交由应用层处理,发送时也一样由应用层提交发送请求后添加head部分再加入待发送队列。
应用层接口,数据传输实现不对应用层开放
namespace SelfFramework.Network
{
/// <summary>
/// Disconnect reason that you receive in OnPeerDisconnected event
/// </summary>
public enum DisconnectReason
{
HeartBroken,
Disconnect,
Exception,
}
/// <summary>
/// Additional information about disconnection
/// </summary>
public struct DisconnectInfo
{
/// <summary>
/// Additional info why peer disconnected
/// </summary>
public DisconnectReason reason;
/// <summary>
/// Error code (if reason is SocketSendError or SocketReceiveError)
/// </summary>
public SocketError errorCode;
public DisconnectInfo(DisconnectReason reason,SocketError error)
{
this.reason = reason;
this.errorCode = error;
}
}
public interface INetEventListener
{
/// <summary>
/// New remote channel connected to host, or client connected to remote host
/// </summary>
/// <param name="channel">Connected channel object</param>
void OnPeerConnected(TChannel channel);
/// <summary>
/// Channel disconnected
/// </summary>
/// <param name="channel">disconnected channel</param>
void OnPeerDisconnected(TChannel channel, DisconnectInfo disconnectInfo);
/// <summary>
/// Network error (on send or receive)
/// </summary>
/// <param name="endPoint">From endPoint (can be null)</param>
/// <param name="socketError">Socket error</param>
void OnNetworkError(TChannel channel, SocketError socketError, SocketAsyncOperation lastOperation);
/// <summary>
/// Received some data
/// </summary>
/// <param name="channel">From channel</param>
/// <param name="reader">DataReader containing all received data</param>
/// <param name="deliveryMethod">Type of received packet</param>
void OnNetworkReceive(TChannel channel, byte[] data);
}
}
数据读写类,写入时自动检查扩容
namespace SelfFramework.Network
{
public class NetDataWriter
{
public byte[] RawData { protected set; get; }
public int Capacity { private set; get; }
public int WritePos { private set; get; }
protected void Resize(int count)
{
if (Capacity - WritePos < count)
{
int newCapacity = this.Capacity << 1;
while (newCapacity < count + Capacity)
{
newCapacity <<= 1;
}
byte[] newData = new byte[newCapacity];
Buffer.BlockCopy(RawData, 0, newData, 0, WritePos);
this.RawData = newData;
this.Capacity = newCapacity;
}
}
public NetDataWriter(int capacity)
{
this.RawData = new byte[capacity];
this.WritePos = 0;
this.Capacity = capacity;
}
public NetDataWriter() : this(64) { }
public static NetDataWriter FormBytes(byte[] bytes, int offset, int count, bool isCopy)
{
if (isCopy)
{
return FormBytes(bytes, offset, count);
}
else
{
NetDataWriter dataWriter = new NetDataWriter();
dataWriter.RawData = bytes;
dataWriter.Capacity = count;
return dataWriter;
}
}
public static NetDataWriter FormBytes(byte[] bytes,int offset,int count)
{
NetDataWriter dataWriter = new NetDataWriter(count);
dataWriter.Append(bytes, offset, count);
return dataWriter;
}
public void Reset(int pos, bool resize = true)
{
if (resize)
{
this.Resize(pos);
}
this.WritePos = pos;
}
public byte[] CopyData()
{
if (this.WritePos == 0)
{
return null;
}
byte[] data = new byte[WritePos];
Buffer.BlockCopy(RawData, 0, data, 0, WritePos);
return data;
}
public byte[] CopyData(int offset)
{
if (this.WritePos < offset || this.Capacity - offset < 0)
{
return null;
}
int count = WritePos - offset;
byte[] data = new byte[count];
Buffer.BlockCopy(RawData, offset, data, 0, count);
return data;
}
public void Append(byte[] data, int offset, int count)
{
Resize(count);
Buffer.BlockCopy(data, offset, RawData, WritePos, count);
WritePos += count;
}
public void Put(byte[] data)
{
Put(data.Length);
Append(data, 0, data.Length);
}
public void Put(byte data)
{
Append(new byte[] { data }, 0, 1);
}
public void Put(int data)
{
Append(BitConverter.GetBytes(data), 0, sizeof(int));
}
public void Put(short data)
{
Append(BitConverter.GetBytes(data), 0, sizeof(short));
}
public void Put(long data)
{
Append(BitConverter.GetBytes(data), 0, sizeof(long));
}
public void Put(string str)
{
byte[] strData=Encoding.UTF8.GetBytes(str);
Put(strData.Length);
Append(strData, 0, strData.Length);
}
public void Put(bool data)
{
Append(BitConverter.GetBytes(data), 0, sizeof(bool));
}
public void PutJson<T>(T data)
{
string json = Util.ObjectToJson<T>(data);
this.Put(json);
}
}
}
namespace SelfFramework.Network
{
public enum PacketProperty
{
}
public class NetDataReader
{
protected byte[] rawData;
public int ReadPos { private set; get; }
public int Capacity { private set; get; }
public NetDataReader() { }
public NetDataReader(NetDataWriter dataWriter)
{
this.SetSources(dataWriter);
}
public NetDataReader(byte[] sources,int offset,int count)
{
SetSources(sources, offset, count);
}
public NetDataReader(byte[] sources) : this(sources, 0, sources.Length) { }
public void SetSources(NetDataWriter dataWriter)
{
this.rawData = dataWriter.RawData;
this.ReadPos = 0;
this.Capacity = dataWriter.WritePos;
}
public void SetSources(byte[] data,int offset,int count)
{
this.rawData = data;
this.ReadPos = offset;
this.Capacity = count;
}
internal byte[] GetBytes(int count)
{
if (this.Capacity < this.ReadPos + count)
{
return null;
}
byte[] data = new byte[count];
Buffer.BlockCopy(this.rawData, ReadPos, data, 0, count);
ReadPos += count;
return data;
}
public byte[] GetBytes()
{
int length = GetInt32();
return GetBytes(length);
}
public byte GetByte()
{
return GetBytes(0)[0];
}
public int GetInt32()
{
return BitConverter.ToInt32(GetBytes(sizeof(int)));
}
public int GetShort()
{
return BitConverter.ToInt16(GetBytes(sizeof(short)));
}
public long GetLong()
{
return BitConverter.ToInt64(GetBytes(sizeof(long)));
}
public string GetString()
{
int length = GetInt32();
byte[] bytes = GetBytes(length);
return Encoding.UTF8.GetString(bytes);
}
public bool GetBool()
{
byte[] data = GetBytes(1);
return BitConverter.ToBoolean(data);
}
public T GetJsonObject<T>()
{
string json = GetString();
return Util.JsonToObject<T>(json);
}
}
}
常量字段,head部分长度,加密使用的私钥存于本地
namespace SelfFramework.Network
{
public sealed class NetConstants
{
private static byte[] key;
internal static byte[] Key
{
get
{
if (key == null)
{
key = Util.ReadFile(@"..\..\..\Config\key.pdk");
}
return key;
}
}
public static int TotalHeadSize
{
get
{
if (AppConst.isEncrypt)
{
return 20; //前四字节为数据包长度,后16字节为IV
}
else
{
return 4;
}
}
}
}
}