基于SuperSocket 1.6版本的自定义帧过滤的源码分析

来源:互联网 发布:mac实用软件 编辑:程序博客网 时间:2024/06/06 00:17

一、SuperSocket 1.6 自定义帧过滤的官方文档地址
http://docs.supersocket.net/v1-6/zh-CN/Implement-Your-Own-Communication-Protocol-with-IRequestInfo,-IReceiveFilter-and-etc

二、此博客的内容
博文描述如何根据官方的模板,实现自己的基于MODBUS的通信帧的过滤。

三、接口及其作用
没有内容

四、实现方法(包含注释)
1.继承FixedHeaderReceiveFilter类

public class MyReceiveFilter : FixedHeaderReceiveFilter<MyRequestInfo>    {        public MyReceiveFilter()            :base(3)        {        }

2.实现2个重载函数

protected override int GetBodyLengthFromHeader(byte[] header, int offset, int length)        {            if (header.Length >= offset + 2)            {                //length为头部(包含1字节的Length长度)                byte data = header[offset+2];                int len = (int)data+2;                //int len = (int)data;                return len;            }            else                return -1;        }
protected override MyRequestInfo ResolveRequestInfo(ArraySegment<byte> header, byte[] bodyBuffer, int offset, int length)        {            byte[] buffer = new byte[header.Array.Length + length];            Buffer.BlockCopy(header.Array, 0, buffer, 0, header.Array.Length);            Buffer.BlockCopy(bodyBuffer, offset, buffer, header.Array.Length, length);            if (true == CRC16.VerifyFrame(buffer, 0, (uint)buffer.Length))            {                MyRequestInfo res = new MyRequestInfo();                string entireFrame = BytesToHEXStr(header.Array) + BytesToHEXStr(bodyBuffer.CloneRange(offset, length));                res.DeviceLogicalCode = entireFrame.Substring(0, 2);                res.Seq = entireFrame.Substring(2, 2);                res.Length = entireFrame.Substring(4, 2);                int dataLen = int.Parse(HEXtoDEC(res.Length));                res.Data = entireFrame.Substring(6, dataLen * 2);                res.Crc = entireFrame.Substring(6 + dataLen * 2, 4);                /*将数据更新到链表*/                List<int> lst_data = new List<int>();                dataLen /= 2;                for (int i = 0; i < dataLen; i++)                {                    int val = ((int)bodyBuffer[offset + 2*i]) * 256 + bodyBuffer[offset + 2*i + 1];                    if (val > 0x8000)/*是个负数*/                        val = (0x8000-(val - 0x8000) + 1);                    lst_data.Add(val);                }                res.DataArray = lst_data;                return res;/*解析出1个完整的帧,则返回实例*/            }            else { return null;/*此缓冲区中并不包含一个完整的帧,则返回 NULL*/ }        }

五、具体的程序运行流程解析
1.自定义帧过滤的上层处理函数的关键代码在 AppSession.cs文件中。
2.当接收到帧之后,程序的调用流程是
IAppSession.ProcessRequest()->FilterRequest()->自定义的帧过滤函数
3.IAppSession.ProcessRequest()部分代码及注释

int IAppSession.ProcessRequest(byte[] readBuffer, int offset, int length, bool toBeCopied)        {            int rest, offsetDelta;            while (true)            {/*这里有一个死循环,正常情况下,在rest<=0的时候会跳出,所以,在Filter()中,只要数据流处理完了,不管是否有效,都要让rest为0*/                var requestInfo = FilterRequest(readBuffer, offset, length, toBeCopied, out rest, out offsetDelta);                if (requestInfo != null)                {                    try                    {                        AppServer.ExecuteCommand(this, requestInfo);                    }                    catch (Exception e)                    {                        HandleException(e);                    }                }                if (rest <= 0)                {                    return offsetDelta;                }                //Still have data has not been processed                offset = offset + length - rest;                length = rest;            }        }        #endregion    }
TRequestInfo FilterRequest(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest, out int offsetDelta)        {            if (!AppServer.OnRawDataReceived(this, readBuffer, offset, length))/*没进去看是干嘛的*/            {                rest = 0;                offsetDelta = 0;                return null;            }            var currentRequestLength = m_ReceiveFilter.LeftBufferSize;/*当前请求的长度,即未处理的数据流长度*/            var requestInfo = m_ReceiveFilter.Filter(readBuffer, offset, length, toBeCopied, out rest);            if (m_ReceiveFilter.State == FilterState.Error)            {/*如果你在自定义的解析函数里面,返回了帧错误,则会进入这里,关闭连接,并返回*/                rest = 0;                offsetDelta = 0;                Close(CloseReason.ProtocolError);                return null;            }            var offsetAdapter = m_ReceiveFilter as IOffsetAdapter;            offsetDelta = offsetAdapter != null ? offsetAdapter.OffsetDelta : 0;            if (requestInfo == null)            {/*如果未解析出一个完整的帧,则让 请求长度 等于 剩余长度(LeftBufferSize与rest的区别在前面提过)*/                //current buffered length                currentRequestLength = m_ReceiveFilter.LeftBufferSize;            }            else            {/*更新 当前请求长度*/                //current request length                currentRequestLength = currentRequestLength + length - rest;            }            if (currentRequestLength >= AppServer.Config.MaxRequestLength)            {                if (Logger.IsErrorEnabled)                    Logger.Error(this, string.Format("Max request length: {0}, current processed length: {1}", AppServer.Config.MaxRequestLength, currentRequestLength));                Close(CloseReason.ProtocolError);                return null;            }            //If next Receive filter wasn't set, still use current Receive filter in next round received data processing            if (m_ReceiveFilter.NextReceiveFilter != null)                m_ReceiveFilter = m_ReceiveFilter.NextReceiveFilter;            return requestInfo;        }
0 0