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

数据包结构

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;
                }
            }
        }
    }
}

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,864评论 6 494
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,175评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,401评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,170评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,276评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,364评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,401评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,179评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,604评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,902评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,070评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,751评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,380评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,077评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,312评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,924评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,957评论 2 351

推荐阅读更多精彩内容