为什么我写的modbus tcpmodbus rtu通信协议议服务器一断,在起来连不上客户端

中国领先的IT技术网站
51CTO旗下网站
浅谈C#使用TCP/IP与ModBus进行通讯
今天我们将谈到工控领域的C#开发,很感谢本文作者写出这样的文章。本文将重点介绍TCP/IP通信方式。
作者:Silent Void来源:博客园| 09:47
Client与Server之间有两种通讯方式:一种是TCP/IP,另一种是通过串口(Serial Port),本文重点介绍第一种通讯方式。第二种方式留了接口,暂时还没有实现。
2. 数据包格式及MBAP header (MODBUS Application Protocol header)
2.1 数据包格式
数据交换过程中,数据包的格式由三部分组成:协议头 + 功能码 + 数据(请求或接受的数据)。
这里主要用到下列两个功能码(十进制):
3: 读取寄存器中的值(Read Multiple Register)
16: 往寄存器中写值(Write Multiple Register)
2.2 MBAP header
协议头具体包括下列4个字段:
(1) Transaction Identifier:事务ID标识,Client每发送一个Request数据包的时候,需要带上该标识;当Server响应该请求的时候,会把该标识复制到Response中;这样客户端就可以进行容错判断,防止数据包发串了。
(2) Protocal Identifier:协议标识,ModBus协议中,该值为0;
(3) Length:整个数据包中,从当个前这个字节之后开始计算,后续数据量的大小(按byte计算)。
(4) Unit Identifier:
3. 大小端转换
ModBus使用Big-Endian表示地址和数据项。因此在发送或者接受数据的过程中,需要对数据进行转换。
3.1 判断大小端
对于整数1,在两种机器上有两种不同的标示方式,如上图所示;因此,我们可以用&操作符来取其地址,再转换成指向byte的指针(byte*),最后再取该指针的值;若得到的byte值为1,则为Little-Endian,否则为Big-Endian。
unsafe&{ &inttester&=&1; &boollittleEndian&=&(*(byte*)(&tester))&==&(byte)1; &} &
3.2 整数/浮点数转换成Byte数组
.Net提供了现成的API,可以BitConverter.GetBytes(value)和BitConverter.ToXXOO(Byte[] data)来进行转换。下面的代码对该转换进行了封装,加入了Little-Endian转Big-Endian的处理(以int为例):
publicclassValueHelper&&{ &publicvirtualByte[]&GetBytes(intvalue) &{ &returnBitConverter.GetBytes(value); &} &publicvirtualintGetInt(byte[]&data) &{ &returnBitConverter.ToInt32(data,&0); &} &} &internalclassLittleEndianValueHelper&:&ValueHelper&&{ &publicoverrideByte[]&GetBytes(intvalue) &{ &returnthis.Reverse(BitConverter.GetBytes(value)); &} &publicvirtualintGetInt(byte[]&data) &{ &returnBitConverter.ToInt32(this.Reverse(data),&0); &} &privateByte[]&Reverse(Byte[]&data) &{ &Array.Reverse(data); & &} &}&
4. 事务标识和缓冲处理
4.1 Transaction Identifier
上面2.2节中提到,Client每发送一个Request数据包的时候,需要带上一个标识;当Server响应该请求的时候,会把该标识复制到Response中,返回给Client。这样Client就可以用来判断数据包有没有发串。在程序中,可以可以用一个变量及记录该标识:
privatebytedataIndex&=&0; &&protectedbyteCurrentDataIndex &{ &get&{&returnthis.dataI&} &} &protectedbyteNextDataIndex() &{ &return++this.dataI &} &
每次Client发送数据的时候,调用NextDataIndex()来取得事务标识;接着当Client读取Server的返回值的时候,需要判断数据包中的数据标识是否与发送时的标志一致;如果一致,则认为数据包有效;否则丢掉无效的数据包。
4.2 缓冲处理
上节中提到,如果Client接收到的响应数据包中的标识,与发送给Server的数据标识不一致,则认为Server返回的数据包无效,并丢弃该数据包。
如果只考虑正常情况,即数据木有差错,Client每次发送请求后,其请求包里面包含需要读取的寄存器数量,能算出从Server返回的数据两大小,这样就能确定读完Server返回的所有缓冲区中的数据;每次交互后,Socket缓冲区中都为空,则整个过程没有问题。但是问题是:如果Server端出错,或者数据串包等异常情况下,Client不能确定Server返回的数据包(占用的缓冲区)有多大;如果缓冲区中的数据没有读完,下次再从缓冲区中接着读的时候,数据包必然是不正确的,而且会错误会一直延续到后续的读取操作中。
因此,每次读取数据时,要么全部读完缓冲区中的数据,要么读到错误的时候,就必须清楚缓冲区中剩余的数据。网上搜了半天,木有找到Windows下如何清理Socket缓冲区的。有篇文章倒是提到一个狠招,每次读完数据后,直接把Socket给咔嚓掉;然后下次需要读取或发送数据的时候,再重新建立Socket连接。
回过头再来看,其实,在Client与Server进行交互的过程中,Server每次返回的数据量都不大,也就一个MBAP Header + 几十个寄存器的值。因此,另一个处理方式,就是每次读取尽可能多的数据(多过缓冲区中的数据量),多读的内容,再忽略掉。暂时这么处理,期待有更好的解决方法。
5.1 类图结构:
5.2 使用示例
(1) 写入数据:
this.Wrapper.Send(Encoding.ASCII.GetBytes(this.tbxSendText.Text.Trim())); &publicoverridevoidSend(byte[]&data) &{ &&if(data.Length&&60) &{ &var&input&=& &data&=&newByte[60]; &Array.Copy(input,&data,&input.Length); &} &this.Connect(); &List&byte&values&=&newList&byte&(255); &&values.AddRange(ValueHelper.Instance.GetBytes(this.NextDataIndex()));&values.AddRange(newByte[]&{&0,&0&});&Protocol&Identifier,0&=&MODBUS&protocol &values.AddRange(ValueHelper.Instance.GetBytes((byte)(data.Length&+&7)));&后续的Byte数量 &values.Add(0);&Unit&Identifier:This&field&is&used&for&intra-system&routing&purpose. &values.Add((byte)FunctionCode.Write);&Function&Code&:&16&(Write&Multiple&Register) &values.AddRange(ValueHelper.Instance.GetBytes(StartingAddress));&values.AddRange(ValueHelper.Instance.GetBytes((short)(data.Length&/&2)));&values.Add((byte)data.Length);&&values.AddRange(data);&&this.socketWrapper.Write(values.ToArray()); &&Application.DoEvents(); &&byte[]&responseHeader&=&this.socketWrapper.Read(12); &} &
(2) 读取数据:
this.tbxReceiveText.Text&=&Encoding.ASCII.GetString(this.Wrapper.Receive()); &publicoverridebyte[]&Receive() &{ &this.Connect(); &List&byte&sendData&=&newList&byte&(255); &&sendData.AddRange(newByte[]&{&0,&0&});&sendData.Add(0);&Unit&Identifier:This&field&is&used&for&intra-system&routing&purpose. &sendData.Add((byte)FunctionCode.Read);&sendData.AddRange(ValueHelper.Instance.GetBytes(StartingAddress));&sendData.AddRange(ValueHelper.Instance.GetBytes((short)30));&this.socketWrapper.Write(sendData.ToArray());&&&Application.DoEvents(); &&shortidentifier&=&(short)((((short)receiveData[0])&&&8)&+&receiveData[1]); &&if(identifier&!=&this.CurrentDataIndex)&&{ &returnnewByte[0]; &} &bytelength&=&receiveData[8];&byte[]&result&=&newbyte[length]; &Array.Copy(receiveData,&9,&result,&0,&length); & &}&
(3) 测试发送和读取:
5.3 代码下载
原文链接:/happyhippy/archive//2108976.html
【编辑推荐】
【责任编辑: TEL:(010)】
大家都在看猜你喜欢
原创原创原创头条热点
24H热文一周话题本月最赞
讲师:108841人学习过
讲师:153655人学习过
讲师:228289人学习过
精选博文论坛热帖下载排行
osCommerce是一款免费的、开放源代码的专业电子商务解决方案。本书以通俗易懂的语言向读者展示了该软件强大的功能和简易的操作方法,主要内...
订阅51CTO邮刊2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2017年2月 总版技术专家分月排行榜第三
2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
2017年2月 总版技术专家分月排行榜第三
2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
2017年2月 总版技术专家分月排行榜第三
2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2017年2月 总版技术专家分月排行榜第三
2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
2017年2月 总版技术专家分月排行榜第三
2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2017年2月 总版技术专家分月排行榜第三
2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
2015年3月 总版技术专家分月排行榜第二2014年12月 总版技术专家分月排行榜第二2014年9月 总版技术专家分月排行榜第二
2015年3月 .NET技术大版内专家分月排行榜第一2015年2月 .NET技术大版内专家分月排行榜第一2015年1月 .NET技术大版内专家分月排行榜第一2014年12月 .NET技术大版内专家分月排行榜第一2014年11月 .NET技术大版内专家分月排行榜第一
本帖子已过去太久远了,不再提供回复功能。通讯-C# 客户端和服务端连接时出现服务端运行一段时间后切断连接
作者:用户
浏览:366 次
C#客户端和服务端连接时出现服务端运行一段时间后切断连接各位大神,现在遇到一个问题:我的客户端程序与服务端进行数据通讯,用到的通讯协议为Modbustcp和FTP,但现在在运行的过程中出现一个问题,就
C# 客户端和服务端连接时出现服务端运行一段时间后切断连接
各位大神,现在遇到一个问题:
我的客户端程序与服务端进行数据通讯,用到的通讯协议为Modbus tcp和FTP,
但现在在运行的过程中出现一个问题,就是我的客户端程序运行一段时间后,服务端直接切断了与我客户端程序的连接(此时我的客户端程序也没有报错,可是我使用了try,catch语句进行报错的),与此同时,我通过输入FTP地址直接登录也不行,提示的错误为与服务器的连接被重置,这个问题是处在我的客户端程序还是服务端?我查了两天的错误,实在不知道错误在哪,还望大神指导。
用心跳包维持连接。你查一下你的协议里面有没有关于心跳包的协议。如果有的话,定期发一个心跳包就可以解决你的问题。
解决方案二:
机上有没有运行防火墙或者别的软件,故障出现的条件有没有规律,比如特定的时间间隔,或者某个操作必然引起。出现故障的时候是所有客户端还是某个客户端等等
解决方案三:
解决方案四:
解决方案五:
【云栖快讯】红轴机械键盘、无线鼠标等753个大奖,先到先得,云栖社区首届博主招募大赛9月21日-11月20日限时开启,为你再添一个高端技术交流场所&&
稳定可靠、可弹性伸缩的在线数据库服务,全球最受欢迎的开源数据库之一
6款热门基础云产品6个月免费体验;2款产品1年体验;1款产品2年体验
弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率
开发者常用软件,超百款实用软件一站式提供其他回答(1)
找个对应的开源客户端,c#的话建议用NModbus这个,很简单的。有相应的例子。
&&&您需要以后才能回答,未注册用户请先。}

我要回帖

更多关于 modbus tcp通讯协议 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信