当前位置: 首页 > news >正文

asp网站的缺点厦门市建设局网站咨询电话

asp网站的缺点,厦门市建设局网站咨询电话,为 wordpress 的评论链接加上 nofollow,中国空间站首次太空授课对于Modbus TCP来说与Modbus RTU和Modbus ASCII有比较大的区别#xff0c;因为它是运行于以太网链路之上#xff0c;是运行于TCP/IP协议之上的一种应用层协议。在协议栈的前两个版本中#xff0c;Modbus TCP作为客户端时也存在一些局限性。我们将对这些不足作一定更新。 1、…对于Modbus TCP来说与Modbus RTU和Modbus ASCII有比较大的区别因为它是运行于以太网链路之上是运行于TCP/IP协议之上的一种应用层协议。在协议栈的前两个版本中Modbus TCP作为客户端时也存在一些局限性。我们将对这些不足作一定更新。 1、存在的不足 在原有的协议栈中我们所封装的Modbus TCP客户端一个特定的客户端即它只是一个客户端实例。在通常的应用中不会有什么问题但在有些应用场合就会显现出它的局限性。 首先作为一个特定的客户端若是连接多个服务器目标时修改服务器参数值的处理变的非常复杂需要分辨是不同的服务器不同的变量。当需要从不同的网段操作数据时我们甚至需要标记不同的网段。 其次作为一个特定的客户端如果我们操作的服务器参数相似时哪怕来自于不同的网段我们也需要仔细分辨或者传递额外的参数。因为同一客户端的解析函数是同一个。 最后将多个Modbus TCP服务器通讯都作为唯一的一个特定的服务器来处理使得各部分混杂在一起程序结构很不清晰对象也不明确。 2、更新设计 考虑到前述的局限性我们将Modbus TCP客户端及其所访问的Modbus TCP服务器定义为通用的对象而当我们在具体应用中使用时再将其特例化为特定的客户端和服务器对象。 首先我们来考虑客户端原则上我们规划的每一个客户端对象管理我们设备上的一个IP网段的设备。那么在一个特定客户端下我们可以定义多达253个不同的服务器。如下图所示 从上图中我们可以发现我们的目的就是让协议栈支持多客户端和多服务器并且在不同客户端下可以访问同网段的多个服务器。接下来我们还需要考虑服务器对象。客户端对服务器的操作无非两类读服务器信息和写服务器信息。 对于读服务器信息来说客户端需要发送请求命令等待服务器返回响应信息然后客户端解析收到的信息并更新对应的参数值。因为返回的响应消息是没有对应的寄存器地址的所以要想在解析的时候定位寄存器就必须知道发送的命令为了便于分辨我们将命令存放在服务器对象中。 而对于写服务器操作无论写的要求来自于哪里对于协议栈来说肯定是其它的数据处理进程发过来的所接到要求后我们需要记录是哪一个客户端管理的哪一个服务器的哪些参数。对于客户端我们不需要分辨因为每个客户端都是独立的处理进程但是对于服务器和参数我们就需要分辨。每一个客户端所管理的IP地址的最后一段为0到255所以我们可以依据来分辨服务器端。而在每一个服务器节点中增加状态标志用以记录请求状态而所有服务器端组成链表。 3、编码实现 我们已经设计了我们的更新接下来我们就根据这一设计来实现它。我们主要从以下几个方面来操作第一实现客户端对象类型和服务器对象类型第二客户端对象的实例化及服务器对象的实例化第三读服务器参数的客户端操作过程第四写服务器参的数客户端操作过程。接下来我们将一一描述之。 3.1、定义对象类型 与在Modbus RTU和Modbus ASCII一样在Modbus TCP协议栈的封装中我们也需要定义客户端对象和服务器对象自然也免不了要定义这两种类型。 首先我们来定义本地客户端的类型其成员包括一个uint32_t的写服务器标志数组服务器数量字段服务器顺序字段本客户端所管理的服务器列表4个数据更新函数指针。具体定义如下 /* 定义本地TCP客户端对象类型 */ typedef struct LocalTCPClientType{uint32_t transaction; //事务标识符uint16_t cmdNumber; //读服务器命令的数量uint16_t cmdOrder; //当前从站在从站列表中的位置uint8_t (*pReadCommand)[12]; //读命令列表ServerListHeadNode ServerHeadNode; //Server对象链表的头节点UpdateCoilStatusType pUpdateCoilStatus; //更新线圈量函数UpdateInputStatusType pUpdateInputStatus; //更新输入状态量函数UpdateHoldingRegisterType pUpdateHoldingRegister; //更新保持寄存器量函数UpdateInputResgisterType pUpdateInputResgister; //更新输入寄存器量函数 }TCPLocalClientType; 关于客户端对象类型在前面的更新设计中已经讲的很清楚了只有Server对象链表的头节点字段需要说明一下。该字段包括两个类容第一服务器链表的头节点指针用来记录服务器对象列表。第二记录链表的长度即服务器节点的数量。具体如下图所示 还需要定义服务器对象此服务器对象只是便于客户端而用于表示真是的服务器。客户端的服务器列表中就是此对象。具体结构如下 /* 定义被访问TCP服务器对象类型 */ typedef struct AccessedTCPServerType{union {uint32_t ipNumber;uint8_t ipSegment[4];}ipAddress; //服务器的IP地址uint32_t flagPresetServer; //写服务器请求标志WritedCoilListHeadNode pWritedCoilHeadNode; //可写的线圈量列表WritedRegisterListHeadNode pWritedRegisterHeadNode; //可写的保持寄存器列表struct AccessedTCPServerType *pNextNode; //下一个TCP服务器节点 }TCPAccessedServerType; 关于服务器对象有三个字段需要说明一下。首先我们来看一看“读命令列表uint8_t (*pReadCommand)[12]”字段它是12个字节这是由Modbus TCP消息格式决定的。如下 我们看到协议标识符为0是因为0就表示Modbus TCP。还有可写的线圈量列表头节点和可写的保持寄存器列表头节点。这两个字段用来表示对线圈和保持寄存器的列表即数量。 3.2、实例化对象 我们定义了客户端即服务器对象类型我们在使用时就需要实例化这些对象。一般来说一个IP网段我们将其实例化为一个客户端对象。 TCPLocalClientType hgraClient; /*初始化TCP客户端对象*/ InitializeTCPClientObject(hgraClient,2,hgraServer,NULL,NULL,NULL,NULL); 而一个客户端对象会管理1到253个服务器对象所以我们可以将多个服务器对象实例组成数组并将其赋予客户端管理。 TCPAccessedServerType hgraServer[]{{{192,168,0,1},0x00,0x00},{{192,168,1,1},0x00,0x00}}; 所以根据客户端和服务器实例化的条件我们需要先实例化服务器对象才能完整实例化客户端对象。在客户端的初始化中我们这里将4的数据处理函数指针初始化为NULL有一个默认的处理函数会复制给它该函数是上一版本的延续在简单应用时简化操作。服务器的上一个发送的命令指针也被赋值为NULL因为初始时还没有命令发送。 3.3、读服务器操作 读服务器操作原理上与以前的版本是一样的。按照一定的顺序给服务器发送命令再对收到的消息进行解析。我们对客户端及其所管理的服务器进行了定义将发送命令保存于服务器对象将服务器列表保存于客户端对象所以我们需要对解析函数进行修改。 /*解析收到的服务器相应信息*/ void ParsingServerRespondMessage(TCPLocalClientType *client,uint8_t *recievedMessage) {/*判断接收到的信息是否有相应的命令*/int cmdIndexFindCommandForRecievedMessage(client,recievedMessage);if((cmdIndex0)) //没有对应的请求命令事务号不相符{return;}if((recievedMessage[2]!0x00)||(recievedMessage[3]!0x00)) //不是Modbus TCP协议{return;}if(recievedMessage[7]0x04) //功能码大于0x04则不是读命令返回{return;}uint16_t mLength(recievedMessage[4]8)recievedMessage[4];uint16_t dLength(uint16_t)recievedMessage[8];if(mLength!dLength3) //数据长度不一致{return;}FunctionCode fuctionCode(FunctionCode)recievedMessage[7];if(fuctionCode!client-pReadCommand[cmdIndex][7]){return;}uint16_t startAddress(uint16_t)client-pReadCommand[cmdIndex][8];startAddress(startAddress8)(uint16_t)client-pReadCommand[cmdIndex][9];uint16_t quantity(uint16_t)client-pReadCommand[cmdIndex][10];quantity(quantity8)(uint16_t)client-pReadCommand[cmdIndex][11];if(quantity*2!dLength) //请求的数据长度与返回的数据长度不一致{return;}if((fuctionCodeReadCoilStatus)(fuctionCodeReadInputRegister)){HandleServerRespond[fuctionCode-1](client,recievedMessage,startAddress,quantity);} } 解析函数的主要部分是在检查接收到的消息是否是合法的Modbus TCP消息。检查没问题则调用协议站解析。而最后调用的数据处理函数则是我们需要在具体应用中编写。在前面客户端初始化时回调函数我们初始化为NULL实际在协议占中有弱化的函数定义需要针对具体的寄存器和变量地址实现操作。 3.4、写服务器操作 写服务器操作则是在其它进程请求后我们标识需要写的对象再统一处理。对具体哪个服务器的写标识存于客户端实例。而该服务器的哪些变量需要写则记录在服务器实例中。 所以在进程检测到需要写一个服务器时则置位对应的位即改变flagWriteServer中的对应位。而需要写该服务器的哪些变量则标记flagPresetCoil和flagPresetReg的对应位。修改这些标识都在其它请求更改的进程中实现而具体的写操作则在本客户端进程中检测到标志位的变化统一执行。 这部分不修改协议栈的代码因为各服务器及各变量都只与具体对象相关联所以在具体的应用中修改。 4、回归验证 借鉴前面Modbus ASCII和Modbus RTU的回归测试经验我们设计两个网段、每网段包括一个客户端及两个服务器的网络结构。但考虑到我们只是功能性验证所以我们设计相对简单的服务器。所以我们设计的网络为协议栈建立2个客户端每个客户端管理同一网段的2个服务器每个服务器有8个线圈及2个保持寄存器。具体结构如图 从上图我们知道该Modbus网关需要实现一个Modbus服务器用于和上位的通讯需要实现两个Modbus客户端用于和下位的通讯。 在这个实验中读操作没有什么需要说的只需要发送命令解析返回消息即可。所以我们中点描述一下为了方便操作在需要写的连续段我们只要找到第一个请求写的位置后就将后续连续可写数据一次性写入。 告之源代码可上Github下载https://github.com/foxclever/Modbus 欢迎关注
http://www.pierceye.com/news/279837/

相关文章:

  • 郑州做网站公司中天猫商城的商品来源
  • 织梦网站首页互联网保险平台排名
  • 免费做链接的网站做动画相册在哪个网站好
  • 做思维导图好看的网站可以做富集分析的网站
  • wordpress 媒体库 cos百度网站怎样优化排名
  • 自助建站程序html样式模板
  • 公主岭网站建设筑梦网站建设
  • 昊源建设监理有限公司网站广州住房与城乡建设部网站
  • 如何免费建立自己网站wordpress媒体优化
  • 南京企业做网站网站建设的类型有几种
  • 不需要证件做网站相城区建设网站
  • 游戏推广网站如何做的全网投放广告的渠道有哪些
  • 飞数石家庄网站建设seo 关键词优化
  • 织梦新手网站建设建筑工程公司资质
  • 网站建设开什么名目外贸网站建设关键点
  • 大学生网站设计河南省建筑工程信息网
  • 安徽省住房和城乡建设厅网站首页wordpress评论框中加文字提示
  • 南京营销型网站建设公司杭州模板建站代理
  • 网页设计比较优秀的网站沈阳网站推广公司
  • 西安网站建设维护如何免费制作app软件
  • 用 net做网站大理市城乡建设局网站
  • 怎么在建筑网站做翻译兼职哈尔滨 高端网站建设
  • 网站建设颜色注意事项优化网站要怎么做
  • 作图神器沧州网站优化
  • 做水果的网站有哪些公司网页设计作品
  • 电子商务网站运营流程北京app制作
  • 怎么在百度推广自己的网站市级部门网站建设自评报告
  • 德州做网站优化专门做酒的网站
  • 旅游网站建设案例分析北京seo案例
  • 网站建设公司 优势单页网站对攻击的好处