基于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
- 基于SuperSocket 1.6版本的自定义帧过滤的源码分析
- mahout基于项目的协同过滤源码分析
- 基于SuperSocket的IIS主动推送消息给android客户端
- 使用SuperSocket实现TLV自定义协议网络通信的Demo
- Mahout基于项目的协同过滤算法源码分析(1)--PreparePreferenceMatrixJob
- Mahout基于项目的协同过滤算法源码分析(2)--RowSimilarityJob
- Mahout基于项目的协同过滤算法源码分析(3)--RowSimilarityJob
- Mahout基于项目的协同过滤算法源码分析(4)共生矩阵乘法
- Mahout基于项目的协同过滤算法源码分析(5)--推荐
- Mahout基于项目的协同过滤算法源码分析(6)--总结
- Mahout并行基于物品的协同过滤算法源码分析(Distributed item-based CF)
- superSocket和android的通讯
- 深入理解Spark 2.1 MLlib(一):基于ALS矩阵分解的协同过滤算法与源码分析
- 基于用户的协同过滤算法的系统多样性分析
- 基于Windows系统下网络数据包过滤方法的分析
- Web分析技术: 下一代基于云的URL过滤
- Apache Mahout基于商品的协同过滤算法流程分析
- 基于SuperSocket实现的WebSocket服务器 和Unity中使用Websocket
- Haar特征初级
- php读取zip注释
- Throwable:Invalid stub element type in index
- iOS性能优化
- hdu1004 Let the Balloon Rise && hdu1263 水果(map)
- 基于SuperSocket 1.6版本的自定义帧过滤的源码分析
- 使用ivy管理项目需要的jar包
- JS属性访问表达式之对象访问属性点方式和中括号方式的区别
- 【PHP】microtime 与 time 函数介绍
- iOS开发网络篇—监测网络状态
- Java CopyOnWriteArrayList 源码分析
- Java千百问_02基本使用(001)_如何用记事本编写Java程序
- 用指针替换全局变量
- 理解C++ dynamic_cast