C#数据交互服务器(一)

数据包结构

1、数据包由head+body组成,head为明文,body可加密。
因为使用的是TCP协议不需要分段,head为4字节,存储整个数据包长度,加密模式开启时为20字节,后16字节存储IV。收到一个完整的数据包后去掉head部分交由应用层处理,发送时也一样由应用层提交发送请求后添加head部分再加入待发送队列。

项目地址

应用层接口,数据传输实现不对应用层开放

namespace SelfFramework.Network
{
    /// 
    /// Disconnect reason that you receive in OnPeerDisconnected event
    /// 
    public enum DisconnectReason
    {
        HeartBroken,
        Disconnect,
        Exception,
    }

    /// 
    /// Additional information about disconnection
    /// 
    public struct DisconnectInfo
    {
        /// 
        /// Additional info why peer disconnected
        /// 
        public DisconnectReason reason;

        /// 
        /// Error code (if reason is SocketSendError or SocketReceiveError)
        /// 
        public SocketError errorCode;

        public DisconnectInfo(DisconnectReason reason,SocketError error)
        {
            this.reason = reason;
            this.errorCode = error;
        }
    }

    public interface INetEventListener
    {
        /// 
        /// New remote channel connected to host, or client connected to remote host
        /// 
        /// Connected channel object
        void OnPeerConnected(TChannel channel);

        /// 
        /// Channel disconnected
        /// 
        /// disconnected channel
        void OnPeerDisconnected(TChannel channel, DisconnectInfo disconnectInfo);

        /// 
        /// Network error (on send or receive)
        /// 
        /// From endPoint (can be null)
        /// Socket error
        void OnNetworkError(TChannel channel, SocketError socketError, SocketAsyncOperation lastOperation);

        /// 
        /// Received some data
        /// 
        /// From channel
        /// DataReader containing all received data
        /// Type of received packet
        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 data)
        {
            string json = Util.ObjectToJson(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()
        {
            string json = GetString();
            return Util.JsonToObject(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;
                }
            }
        }
    }
}

C#数据交互服务器(二)
C#数据交互服务器(三)
Rijndael加密算法
WinSock IO模型实现

你可能感兴趣的:(C#数据交互服务器(一))