新文章 网摘 文章 随笔 日记

自己写的TCP自定义二进制协议(一)

using System;
using System.Linq;
using System.Reflection;
using BinaryProtocol.Core.Attributes;

namespace BinaryProtocol.Core.Coder
{
    public class BitDecoder<T>
    {
        private readonly byte[] _objBytes;
        public BitDecoder(byte[] objBytes)
        {
            _objBytes = objBytes;
            Decode();
        }

        public T Value { get; private set; }

        private void Decode()
        {
            int index = 0;
            T obj = Activator.CreateInstance<T>();
            var type = typeof(T);

            PropertyInfo[] properties;
            if (!PropertyDictionary.ContainsKey(type.FullName))
            {
                properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                    .Where(r => r.CustomAttributes.Select(t => t.AttributeType).Contains(typeof(FieldIndex)))
                    .OrderBy(r => ((FieldIndex)r.GetCustomAttributes(typeof(FieldIndex), false).FirstOrDefault()).Index).ToArray();
                PropertyDictionary.Add(type.FullName, properties);
            }
            else
            {
                properties = PropertyDictionary.Cache[type.FullName];
            }

            foreach (var p in properties)
            {
                byte[] bytes;
                byte[] bytes2;
                switch (p.PropertyType.Name)
                {
                    case "String":
                        bytes = new byte[2];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 2);
                        bytes2 = bytes.Reverse().ToArray();
                        var strLen = BitConverter.ToUInt16(bytes2, 0);
                        index += 2;

                        var str = System.Text.Encoding.UTF8.GetString(_objBytes, index, strLen);
                        p.SetValue(obj, str);
                        index += strLen;
                        break;
                    case "DateTime":
                        var format = "yyyy-MM-dd HH:mm:ss fff";
                        var dateLen = System.Text.Encoding.UTF8.GetBytes(format).Length;
                        var dateStr = System.Text.Encoding.UTF8.GetString(_objBytes, index, dateLen);
                        DateTime date = GetDateTime(dateStr);
                        p.SetValue(obj, date);
                        index += dateLen;
                        break;
                    case "Boolean":
                        bytes = new byte[1];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 1);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToBoolean(bytes2, 0));
                        index += 1;
                        break;
                    case "Char":
                        bytes = new byte[2];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 2);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToChar(bytes2, 0));
                        index += 2;
                        break;
                    case "Byte":
                        bytes = new byte[2];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 2);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, Convert.ToByte(BitConverter.ToInt16(bytes2, 0)));//这里可能有毛病
                        index += 2;
                        break;
                    case "Int16":
                        bytes = new byte[2];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 2);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToInt16(bytes2, 0));
                        index += 2;
                        break;
                    case "Int32":
                        bytes = new byte[4];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 4);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToInt32(bytes2, 0));
                        index += 4;
                        break;
                    case "Int64":
                        bytes = new byte[8];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 8);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToInt64(bytes2, 0));
                        index += 8;
                        break;
                    case "Single":
                        bytes = new byte[4];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 4);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToSingle(bytes2, 0));
                        index += 4;
                        break;
                    case "Double":
                        bytes = new byte[8];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 8);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToDouble(bytes2, 0));
                        index += 8;
                        break;
                    case "SByte":
                        bytes = new byte[2];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 2);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, Convert.ToSByte(BitConverter.ToUInt16(bytes2, 0)));//这里可能有毛病
                        index += 2;
                        break;
                    case "UInt16":
                        bytes = new byte[2];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 2);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToUInt16(bytes2, 0));
                        index += 2;
                        break;
                    case "UInt32":
                        bytes = new byte[4];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 4);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToUInt32(bytes2, 0));
                        index += 4;
                        break;
                    case "UInt64":
                        bytes = new byte[8];
                        Buffer.BlockCopy(_objBytes, index, bytes, 0, 8);
                        bytes2 = bytes.Reverse().ToArray();
                        p.SetValue(obj, BitConverter.ToUInt64(bytes2, 0));
                        index += 8;
                        break;
                }
            }
            Value = obj;
        }

        /// <summary>
        /// 带毫秒的字符转换成时间(DateTime)格式
        /// 可处理格式:[2014-10-10 10:10:10,666 或 2014-10-10 10:10:10 666 或 2014-10-10 10:10:10.666]
        /// </summary>
        private DateTime GetDateTime(string dateTime)
        {
            string[] strArr = dateTime.Split('-', ' ', ':', ',', '.');
            DateTime dt = new DateTime(int.Parse(strArr[0]),
                int.Parse(strArr[1]),
                int.Parse(strArr[2]),
                int.Parse(strArr[3]),
                int.Parse(strArr[4]),
                int.Parse(strArr[5]),
                int.Parse(strArr[6]));
            return dt;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using BinaryProtocol.Core.Attributes;

namespace BinaryProtocol.Core.Coder
{
    public class BitEncoder<T>
    {
        private readonly T _obj;
        public BitEncoder(T obj)
        {
            _obj = obj;
            Encode();
        }

        public byte[] Bytes { get; private set; }

        private void Encode()
        {
            if (_obj == null)
            {
                Bytes = new byte[0];
            }
            List<byte> byteList = new List<byte>();
            var type = _obj.GetType();
            PropertyInfo[] properties;
            if (!PropertyDictionary.ContainsKey(type.FullName))
            {
                properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                    .Where(r => r.CustomAttributes.Select(t => t.AttributeType).Contains(typeof(FieldIndex)))
                    .OrderBy(r => ((FieldIndex)r.GetCustomAttributes(typeof(FieldIndex), false).FirstOrDefault()).Index).ToArray();
                PropertyDictionary.Add(type.FullName, properties);
            }
            else
            {
                properties = PropertyDictionary.Cache[type.FullName];
            }

            foreach (var p in properties)
            {
                var value = p.GetValue(_obj);

                switch (p.PropertyType.Name)
                {
                    case "String":
                        var strBytes = System.Text.Encoding.UTF8.GetBytes(value.ToString());
                        Int16 len = (short)strBytes.Length;
                        var bytes = BitConverter.GetBytes(len).Reverse();
                        byteList.AddRange(bytes);
                        byteList.AddRange(strBytes);
                        break;
                    case "DateTime":
                        var format = "yyyy-MM-dd HH:mm:ss fff";
                        var dateStr = ((DateTime)value).ToString(format);
                        var dateBytes = System.Text.Encoding.UTF8.GetBytes(dateStr);
                        byteList.AddRange(dateBytes.ToList());
                        break;
                    case "Boolean":
                        byteList.AddRange(BitConverter.GetBytes((bool)value).Reverse().ToList());
                        break;
                    case "Char":
                        byteList.AddRange(BitConverter.GetBytes((char)value).Reverse().ToList());
                        break;
                    case "Byte":
                        byteList.AddRange(BitConverter.GetBytes((Byte)value).Reverse().ToList());
                        break;
                    case "Int16":
                        byteList.AddRange(BitConverter.GetBytes((Int16)value).Reverse().ToList());
                        break;
                    case "Int32":
                        byteList.AddRange(BitConverter.GetBytes((Int32)value).Reverse().ToList());
                        break;
                    case "Int64":
                        byteList.AddRange(BitConverter.GetBytes((Int64)value).Reverse().ToList());
                        break;
                    case "Single":
                        byteList.AddRange(BitConverter.GetBytes((float)value).Reverse().ToList());
                        break;
                    case "Double":
                        byteList.AddRange(BitConverter.GetBytes((Double)value).Reverse().ToList());
                        break;
                    case "SByte":
                        byteList.AddRange(BitConverter.GetBytes((SByte)value).Reverse().ToList());
                        break;
                    case "UInt16":
                        byteList.AddRange(BitConverter.GetBytes((UInt16)value).Reverse().ToList());
                        break;
                    case "UInt32":
                        byteList.AddRange(BitConverter.GetBytes((UInt32)value).Reverse().ToList());
                        break;
                    case "UInt64":
                        byteList.AddRange(BitConverter.GetBytes((UInt64)value).Reverse().ToList());
                        break;
                }
            }

            Bytes = byteList.ToArray();
        }
    }
}

 

posted @ 2020-10-21 15:55  岭南春  阅读(195)  评论(0)    收藏  举报