zoukankan      html  css  js  c++  java
  • 高性能TcpServer(C#)

    高性能TcpServer(C#) - 1.网络通信协议

    高性能TcpServer(C#) - 2.创建高性能Socket服务器SocketAsyncEventArgs的实现(IOCP)

    高性能TcpServer(C#) - 3.命令通道(处理:掉包,粘包,垃圾包)

    高性能TcpServer(C#) - 4.文件通道(处理:文件分包,支持断点续传)

    高性能TcpServer(C#) - 5.客户端管理

    高性能TcpServer(C#) - 6.代码下载

    处理原理

    每个client创建各自的byte[]数组,通过遍历每个字节的数据

    1.判断包长,确定掉包;

    2.判断解析完后byte数组是否还有未解析的数据,确定粘包;

    3.判断包头,确定垃圾包;

    缓存数据类

     /// <summary>

        /// 缓存数据类

        /// </summary>

        public class CByteBuffer

        {

            // 默认1k

            int m_iBufferSize = 1024 * 1;

     

            // 数据解析

            byte[] m_abyBuf;

            int m_iPosition = 0;

            int m_iRecvLength = 0;

            bool bWaitRecvRemain;// 数据未接收完等待接收

            object m_lock = new object(); // 内部同步锁

     

            public int Position

            {

                get { return m_iPosition; }

                set { m_iPosition = value; }

            }

     

            public int RecvLength

            {

                get { return m_iRecvLength; }

                set { m_iRecvLength = value; }

            }

     

            public bool WaitRecvRemain

            {

                get { return bWaitRecvRemain; }

                set { bWaitRecvRemain = value; }

            }

     

            public CByteBuffer(int buffSize)

            {

                m_iBufferSize = buffSize;

                m_abyBuf = new byte[m_iBufferSize];

            }

     

            public int GetPosition()

            {

                return m_iPosition;

            }

     

            public int GetRecvLength()

            {

                return m_iRecvLength;

            }

     

            public void Put(SocketAsyncEventArgs e)

            {

                int iLength = e.BytesTransferred;

                if (m_iRecvLength + iLength >= m_iBufferSize)

                {

                    Clear();

                    return;

                }

     

                lock (m_lock)

                {

                    Array.Copy(e.Buffer, e.Offset, m_abyBuf, m_iRecvLength, iLength);

                    m_iRecvLength += iLength;

                }

            }

     

            public byte GetByte()

            {

                bWaitRecvRemain = false;

     

                if (m_iPosition >= m_iRecvLength)

                {

                    bWaitRecvRemain = true;

                    return 0;

                }

     

                byte byRet;

                lock (m_lock)

                {

                    byRet = m_abyBuf[m_iPosition];

                }

                m_iPosition++;

     

                return byRet;

            }

     

            public byte[] GetByteArray(int Length)

            {

                bWaitRecvRemain = false;

     

                if (m_iPosition + Length > m_iRecvLength)

                {

                    bWaitRecvRemain = true;

                    return null;

                }

     

                byte[] ret = new byte[Length];

     

                lock (m_lock)

                {

                    Array.Copy(m_abyBuf, m_iPosition, ret, 0, Length);

     

                    m_iPosition += Length;

                }

     

                return ret;

            }

     

            public bool HasRemaining()

            {

                return m_iPosition < m_iRecvLength;

            }

     

            public int Remaining()

            {

                return m_iRecvLength - m_iPosition;

            }

     

            public void Clear()

            {

                m_iPosition = 0;

                m_iRecvLength = 0;

                bWaitRecvRemain = false;

            }

     

            ~CByteBuffer()

            {

                m_abyBuf = null;

                Dispose(false);

            }

     

            protected virtual void Dispose(bool disposing)

            {

                if (disposing)

                {

                    GC.SuppressFinalize(this);

                }

            }

     

            public void Dispose()

            {

                Dispose(true);

            }

        }

    协议解析类

            public void Process(CByteBuffer bBuffer, CProtocolAnalysis analysis, string sn)

            {

                analysis.BagStatus = CProtocolAnalysis.EBagStatus.BagNone;

                analysis.WhetherToSend = false;

     

                int iPosition = bBuffer.Position;

                byte head1 = 0; byte head2 = 0; byte head3 = 0; byte head4 = 0; byte head5 = 0; byte head6 = 0; bool headok = false;

     

                if (!bBuffer.HasRemaining()) return;

     

                while (bBuffer.HasRemaining())

                {

                    head1 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

                    if (HEAD1 == head1)

                    {

                        iPosition = bBuffer.Position - 1;

                        head2 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

                        head3 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

                        head4 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

                        head5 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

                        head6 = bBuffer.GetByte(); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

                        if (HEAD2 == head2 && HEAD3 == head3 && HEAD4 == head4 && HEAD5 == head5 && HEAD6 == head6)

                        {

                            headok = true;

                            break;

                        }

                        else

                        {

                            CLogHelp.AppendLog("Error,Unable to parse the data2:Position=" + iPosition.ToString() + ",Index=" + (bBuffer.GetPosition()).ToString() + ",Head2=" + head2.ToString());

                        }

                    }

                    else

                    {

                        CLogHelp.AppendLog("Error,Unable to parse the data1:Position=" + iPosition.ToString() + ",Index=" + (bBuffer.GetPosition()).ToString() + ",Head1=" + head1.ToString());

                    }

                }

     

                if (!bBuffer.HasRemaining())

                {

                    if (headok)

                    {

                        if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

                    }

                    return;

                }

     

                byte[] arrlen = bBuffer.GetByteArray(4); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

                int len = CCommonFunc.String2Int(CCommonFunc.ByteToString(arrlen)); if (-1 == len) return;

                byte[] source = bBuffer.GetByteArray(len); if (!analysis.IsRemainData(iPosition, bBuffer, analysis)) return;

     

                if (!bBuffer.HasRemaining())

                {

                    bBuffer.Clear();

                }

                else

                {

                    analysis.BagStatus = CProtocolAnalysis.EBagStatus.BagStick;

                }

     

                // #WaterMeter-001#01##

                string data = CCommonFunc.ByteToString(source);

                if (null == data || 0 == data.Length || data.Length - 1 != data.LastIndexOf(SPLIT1))

                {

                    return;

                }

                data = data.Substring(1, data.Length - 2);

                string[] item = data.Split(SPLIT1);

                if (null == item || 4 != item.Length)

                {

                    return;

                }

                string uid = item[0];

                string taskid = item[1];

                int cmd = CCommonFunc.String2Int(item[2]);

                string content = item[3];

                Program.AddMessage("R: [" + sn + "] cmd=" + cmd.ToString() + " data=" + data);

     

                analysis.Cmd = cmd;

                analysis.Uid = uid;

                analysis.TaskId = taskid;

     

                if (cmd == 1 || cmd == 2 || cmd == 3 || cmd == 4 || cmd == 5 || cmd == 6 || cmd == 7)

                {

                    analysis.WhetherToSend = true;

                }

     

                string softtype = "";  

     

                try

                {

                    switch (cmd)

                    {

                        case 1:

                            analysis.Msg = "ok";

                            break;

                        case 2:

                            analysis.Msg = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

                            break;

                        case 3:

                            // HTEMP=0263#WaterMeter-001#1520557004#03#buildid=44@edmid=37@meterid=1228@senddate=2018-02-05 17:36:22@[{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}+{132,0.0000}]#

                            analysis.Msg = "ok";

                            break;

                        case 4:

                            {

                                // 获取版本信息

                                softtype = content.Split(SPLIT2)[1];

                                StorageFile(softtype, System.Windows.Forms.Application.StartupPath + "\test.zip");

                                analysis.Msg = "2";// version

                            }

                            break;

                        case 5:

                            // 获取包数

                            {

                                softtype = content.Split(SPLIT2)[1];

                                if (!dicSoft.ContainsKey(softtype))

                                {

                                    StorageFile(softtype, System.Windows.Forms.Application.StartupPath + "\test.zip");

                                }

                                // 获取包数

                                int count = 0;

                                FileCut entity = null;

                                dicSoft.TryGetValue(softtype, out entity);

                                if (null != entity) count = entity.Count;

                                analysis.Msg = count.ToString();

                            }

                            break;

                        case 6:

                            // 执行更新动作

                            {

                                string[] items = content.Split(SPLIT2);

                                softtype = items[1];

                                int downindex = CCommonFunc.String2Int(items[2]);

                                if (!dicSoft.ContainsKey(softtype))

                                {

                                    analysis.Msg = "error@" + softtype + " 未找到更新文件,请先获取包数";

                                }

                                else

                                {

                                    FileCut entity = null;

                                    dicSoft.TryGetValue(softtype, out entity);

                                    if (null != entity)

                                    {

                                        string filedata = "";

                                        entity.Data.TryGetValue(downindex, out filedata);

                                        if (string.IsNullOrEmpty(filedata))

                                            analysis.Msg = "error@" + softtype + " 第" + downindex + "包的数据为空";

                                        else

                                            analysis.Msg = filedata;

                                    }

                                }

                            }

                            break;

                        case 7:

                            // 更新版本信息(update sql)

                            analysis.Msg = "ok";

                            break;

                    }

                }

                catch (Exception ex)

                {

                    analysis.Msg = "error@" + ex.Message;

                }

                Program.AddMessage("S: [" + sn + "] cmd=" + cmd.ToString() + " data=" + analysis.Msg);

            }

    测试效果

    正常包

    HTEMP=0026#Meter-001#1533022506#01##

     

    掉包(分两包发送)

    HTEMP=0026#

    Meter-001#1533022506#01##

     

    粘包(两包一起发送)

    HTEMP=0026#Meter-001#1533022506#01##HTEMP=0026#Meter-001#1533022506#01##

     

  • 相关阅读:
    Pyhton 单行、多行注释方法
    laravel中不使用 remember_token时退出报错,如何解决?
    PHP实现打印出库单,有没有实现过?
    是不等号的意思
    PHP如何输出合并单元格的表
    一起谈.NET技术,.Net创建Excel文件(插入数据、修改格式、生成图表)的方法 狼人:
    一起谈.NET技术,ASP.NET MVC 通过 FileResult 向浏览器发送文件 狼人:
    一起谈.NET技术,asp.net Ajax AutoComplete控件使用 狼人:
    一起谈.NET技术,Silverlight 拖动复制控件 狼人:
    一起谈.NET技术,ASP.NET Process Model之二:ASP.NET Http Runtime Pipeline[上篇] 狼人:
  • 原文地址:https://www.cnblogs.com/chen1880/p/11238699.html
Copyright © 2011-2022 走看看