modbus通信协议实现范文

更新时间:2024-03-06 14:15:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

******************* 题 目:

毕业设计说明书

MODBUS通信协议在TCP/IP上的实现

专 业:电子信息工程 学 号:********* 姓 名:******** 指导教师:****

完成日期:2010年5月14日

*************

毕业论文(设计)任务书

论文(设计)题目:

学号: 姓名: 专业: 指导教师: 系主任:

一、主要内容及基本要求

二、重点研究的问题

三、进度安排

序号 1 2 3 4 5 6 7 8

各阶段完成的内容 完成时间 四、应收集的资料及主要参考文献

*********

毕业论文(设计)评阅表

学号 姓名 专业

毕业论文(设计)题目: 评价项目 选题 1.是否符合培养目标,体现学科、专业特点和教学计划的基本要求,达到综合训练的目的; 2.难度、份量是否适当; 3.是否与生产、科研、社会等实际相结合。 能力 1.是否有查阅文献、综合归纳资料的能力; 2.是否有综合运用知识的能力; 3.是否具备研究方案的设计能力、研究方法和手段的运用能力; 4.是否具备一定的外文与计算机应用能力; 5.工科是否有经济分析能力。 论文 (设计)质量 综 合 评 价 1.立论是否正确,论述是否充分,结构是否严谨合理;实验是否正确,设计、计算、分析处理是否科学;技术用语是否准确,符号是否统一,图表图纸是否完备、整洁、正确,引文是否规范; 2.文字是否通顺,有无观点提炼,综合概括能力如何; 3.有无理论价值或实际应用价值,有无创新之处。 评阅人:

2008年 5 月 日 评 价 内 容 ********

毕业论文(设计)鉴定意见

学号: 姓名: 专业: 毕业论文(设计说明书) 页 图 表 张 论文(设计)题目:

内容提要:

指导教师评语 指导教师: 年 月 日 答辩简要情况及评语 答辩小组组长:

年 月 日 答辩委员会意见 答辩委员会主任:

年 月 日

目 录

第一章 引言 ............................................................................................11

1.1 研究背景..................................................................................................................11 1.2 国内外发展现状..................................................................... 错误!未定义书签。 1.3 主要技术路线......................................................................... 错误!未定义书签。 1.4 本文的工作............................................................................. 错误!未定义书签。 1.5 论文的结构安排..................................................................... 错误!未定义书签。

第二章 MODBUS通信模型的构建 ................................... 错误!未定义书签。

2.1 一台设备上的MODBUS模型构建 ..................................... 错误!未定义书签。 2.1.1 用户应用层.................................................................. 错误!未定义书签。

2.1.2 通信应用层.................................................................. 错误!未定义书签。 2.1.3 TCP管理层 ................................................................. 错误!未定义书签。 2.1.4 TCP/IP栈层................................................................. 错误!未定义书签。 2.3 两台设备间通信模型构建..................................................... 错误!未定义书签。 2.3 多台设备总体通信模型构建................................................. 错误!未定义书签。

第三章 MODBUS在TCP/IP上的实现与分析 ..........错误!未定义书签。

3.1 应用层MODBUS协议描述 ................................................. 错误!未定义书签。

3.1.1 TCP/IP上的MODBUS应用数据单元 ..................... 错误!未定义书签。 3.1.2 MBAP报文头描述 ..................................................... 错误!未定义书签。 3.2 套接字简介............................................................................. 错误!未定义书签。 3.3 应用程序与套接字关系......................................................... 错误!未定义书签。

第四章 课题的具体实现流程 ......................................错误!未定义书签。

4.1 编程环境............................................................................... 错误!未定义书签。

4.1.1 Visual C++ 与面向对象 ........................................... 错误!未定义书签。 4.1.2 利用Visual C++ /MFC开发程序 ............................ 错误!未定义书签。 4.2 编程语言............................................................................. 错误!未定义书签。 4.3 套接字实现流程................................................................. 错误!未定义书签。 4.4 MODBUS协议编程体现 .................................................. 错误!未定义书签。

第五章 对程序实现结果的分析 ..................................错误!未定义书签。

5.1 程序实现结果演示 ............................................................. 错误!未定义书签。 5.2 对MODBUS TCP/IP报文的分析 ................................... 错误!未定义书签。

第六章 总结与展望 .....................................................错误!未定义书签。

6.1 总结......................................................................................... 错误!未定义书签。 6.2 展望......................................................................................... 错误!未定义书签。

注释 ...............................................................................错误!未定义书签。 参考文献........................................................................错误!未定义书签。 附录 ...............................................................................错误!未定义书签。

MODBUS通信协议在TCP/IP上的实现

摘要: 伴随着批评家的鄙夷和使用者的称赞, MODBUS/TCP 的确已不再是新生事物。

更何况对于自 1979 年就开始使用的 MODBUS协议,为其增加基于以太网 TCP/IP 的传输技术是绝对由必要的。MODBUS协议本身的 MODBUS 服务和对象模式在MODBUS /TCP 中都没有改变,并简单地采用 TCP/IP 作为数据传输协议。这使得MODBUS拥有了一系列协议,目前包括传统的MODBUS -RTU 、 MODBUS -Plus 和MODBUS -TCP 。所有这些协议都使用相同的应用层协议-规定了统一的用户数据和通讯服务。分析MODBUS/TCP协议构成,通过采用套接字与多线程技术,设计出基于MODBUS /TCP协议的工业以太网通信网络,分析出客户端/服务器的通信模式的主要特性,并给出其具体实现过程。所构建的基于MODBUS /TCP与MODBUS的工业以太网可实现工业现场数据采集、处理及通信等功能,为工业自动化领域的实时网络化通信提供了一种有效的解决方案。

关键词:MODBUS/TCP 、以太网 、 套接字、 工业 、 TCP/IP

MODBUS protocol implementate in the TCP/IP

Abstract: With the contempt of critics and users praise, MODBUS / TCP is indeed no longer a novelty. Moreover, since 1979 began to use the MODBUS protocol, for increase in Ethernet-based TCP / IP transmission technology is absolutely the necessary. MODBUS protocol itself and the object model service MODBUS / TCP were not changed, and simply use TCP / IP as a data transfer protocol. This makes the MODBUS have a series of agreements, currently including traditional MODBUS-RTU, MODBUS-Plus and MODBUS-TCP. All these protocols use the same application layer protocol - provides a unified user data and communication services. Analysis of MODBUS / TCP protocol composition, through the use of socket and multi-threading technology, designed based on MODBUS / TCP protocol Ethernet communications network, analyze the client / server model of the main characteristics of the communication, and gives specific implementation process. Constructed based on MODBUS / TCP and MODBUS industrial Ethernet can achieve industrial data acquisition, processing and communications functions for industrial automation, real-time communication network provides an effective solution.

Keywords: MODBUS / TCP、 Ethernet 、sockets 、industry 、TCP / IP

第1章 引言

1.1 研究背景

在现代化工业控制中, 由于被控对象、测控装置等物理设备的地域分散性, 以及控制与监控等任务对实时性的要求, 不同设备之间现场交互性信息的传递越来越多。但传统的工业控制系统软件存在着一些问题。不具备开放性,各个部分的联系过于紧密,使系统过于复杂。这样使系统的更新、扩展和升级变得非常困难,对系统任何一部分的修改都有可能对其它部分造成影响,从而导致大量且烦琐的软件和硬件的修改。传统的工业控制软件开发中出现的另一个主要问题是软件的重复开发,软件不能够复用,资源不能共享,造成大量的人力与物力资源的浪费。虽然使用高级语言函数库让我们可以利用面向对象的继承等方法大量重用源代码,但这些复用只是对源代码级的复用而不是对可执行文件级的复用。

由于传统工业控制系统的带来的不便, 造成形成了大量的“信息孤岛”,但是,对于工业控制而言,各站点之间不是孤立的,它们必须互相配合、协调才能保证产品质量和实现连续生产,这就需要各站点能互通讯息。另外,上级管理网也需要与子站交互数据,以实现全局的监控和优化。然而,子站是采用不同开发平台、不同通讯协议组成的异构系统,可能由不同的厂家和个为开发。要为每种协议写一个转换接口或驱动是比较繁琐的,特别是在站点和协议较多的时候。因此,怎样有效集成数据,避免信息孤岛的出现,是工业控制领域中常遇到难点问题之一。

比较好的方法是各站点都采用标准协议进行数据通讯,而不必为每一种协议开发一个通讯接口。目前这方面的协议比较多,MODBUS 就是其中的一种。MODBUS是一种全开放, 免费提供,非常容易理解和实施的协议, 从70 年代诞生以来,在制造业、电力、水电、冶金、矿山、交通、基础设施的工业领域中的数据采集和过程控制得到了广泛应用, 形成了一种事实上的工业标准。同时, 随着计算机网络技术的迅速发展, 信息技术已逐步进入工业自动化领域, 以太网技术以高速率、低成本、应用广泛等优势, 促进了它在工控领域的应用, 形成了当前的工业以太网技术。它允许MODBUS协议与以太网TCP/IP 结合, 在TCP 帖中嵌MODBUS信息帧, 成为MODBUS TCP/IP, 在工业自动化领域中, 具有很高的性能价格比, 是一种真正开放的理想解决方案。

1.2 国内外发展现状

目前在全球范围内已经安装了8,000,000套MODBUS串行链路设备和800,000套MODBUS TCP/IP设备,基于MODBUS TCP/IP和Web技术的“透明就绪”的广泛应用可以被归类到三大市场:能源与基础设施,工业,以及建筑行业。

◆ 在能源与基础设施市场,机场、隧道、数字通讯、电信、水处理、油气、能源等行业大大得益于“透明就绪”的远程控制能力

◆ 在工业市场,食品与饮料、微电子、制药、汽车等行业则高度的受益于“透明就绪”中从IT系统贯通到车间层TCP/IP以太网的统一全局网络架构 ◆ 在建筑市场,医疗机构、公用建筑、民用住宅、船舶等行业在“透明就绪”中使用他们原有的TCP/IP以太网网络,从而大大的降低了实施费用

1.3 主要技术路线

MODBUS/TCP协议是在MODBUS协议的基础上发展而来的。为了尽量地使用已有成果,MODBUS / TCP协议的实现是在不改变原有MODBUS协议的基础上,只是将它的传输层协议简单的移植到TCP/IP上。因此在TCP/IP网络中MODBUS /TCP使用传输控制协议(TCP)进行MODBUS应用协议的数据传输。参数和数据使用封装的方法嵌入到TCP报文的用户数据容器中进行传送。另外地址和校验在MODBUS /TCP中也由底层的TCP协议来完成。由于传输层以上遵循MODBUS协议,所以采用C/S结构,在数据传输前进行之前,需要在客户和服务器之间建立一个TCP/IP连接。服务器使用端口502作为MODBUS /TCP连接的端口。连接的建立通常由TCP/IP的Socket接口的软件协议自动实现的,因此对应用完全透明。

一旦客户和服务器之间的TCP/IP连接建立,同样的连接可以根据要求的方向用来传输任意数量的用户数据。客户和服务器还可以同时建立多个TCP/IP连接,最大的连接数量取决于TCP/IP接口的规范。在输入输出数据循环传输的情况下,永久的连接通常维持在客户和服务器之间,只有在发生特殊事件而有必要传送参数和诊断报文时,连接才能在每一次数据传送后被关闭,需要时再次建立。

这也是MODBUS /TCP在工业以太网中采用TCP作为为传输层协议而不采用速度更快的UDP协议的原因所在。

虽然MODBUS /TCP由于在传输层采用TCP协议,而使其不得不在传输层协议以下的诸层采取更有效的实时性策略。但与IDA方案相比,MODBUS /TCP在其开放性、简单和稳定的性能上具有优势,是一个具有较高的性能价格比的工业以太网方案。

1.4 本文的工作

本文主要告诉读者该课题的实现过程。在看到一个用软件编程实现的课题时,应该有的一些思路,需要掌握的一些知识。在拿到一个课题时,首先需要为课题的实现构建一个模型,对于该课题而言,应想到怎样在一台设备上实现MODBUS协议,同时,该课题是实现通信,那么就必然不只一台设备,继而想到两台设备间的通信模型,最后到多台设备的通信结构。建构好模型后,就应该查找相关的理论知识。本文涉及到的理论知识主要包括MODBUS协议结构以及套接字的原理。掌握原理后,接下来就应该设计实现流程。对于软件开发而言,编程环境和编程语言很重要,这会对工作的复杂程度带来很大的影响。选择好编程工具后,就要想着怎样实现课题,应构思一个流程。本文首先需要将TCP/IP应用层以下作为一个整体,而这个整体和上层的接口即是套接字接口。再将套接字接口与应用层MODBUS协议联系,即可实现该课题的要求。摘取程序中最重要的部分进行分析。能够让读者清楚的认识到整个编程实例的精髓。最后对整个课题的实现进行一个总结,带给读者一个实现该课题的基本框架,以及在实现该课题过程中自己的一些见解以、疑问及学到的知识和技术。提出自己对该项技术的展望,以及这项技术的发展前景。

1.5 论文的结构安排

本论文共分五章,各章主要内容如下:

第一章: 介绍本论文所研究的背景,即该课题的实际应用价值。 第二章: 构建了实现课题的模型,从一台设备上实现MODBUS协议,到两

台设备通信,最后构建多台设备的整体通信结构。

第三章:为该课题建立理论基础。该课题涉及到的理论主要包括MODBUS

协议结构及套接字,分析它们之间的关系所在。

第四章: 提出实现该课题的主要流程,分为几个步骤,每个步骤应做的工

作,以及用到的编程环境和编程语言。

第五章:程序实验结果演示,并对MODBUS TCP/IP报文进行分析,通

过分析体现MODBUS协议的数据交换过程。

第六章: 总结与展望。

第二章 基于TCP/IP模型的MODBUS通信协议

2.1 一台设备上的MODBUS模型构建 2.1.1 用户应用层

它和设备应用相对应,与设备完全无关。

2.1.2 通信应用层

一个MODBUS设备可提供一个客户机或服务器的MODBUS接口。可提

供一个MODBUS后端接口,间接地允许对用户应用对象的访问。此接口由四个区域组成:离散量输入、离散量输出(线圈)、输入寄存器和输出寄存器。必须进行这个接口与用户应用数据直接的映射。可将MODBUS通信应用层分为四个小模块,如下:

1、MODBUS客户机

MODBUS客户机允许用户应用显式控制与远程设备的信息交换。MODBUS客户机根据用户应用向MODBUS客户机接口发送的要求中所包含的参数来建立一个MODBUS请求。

2、MODBUS客户机接口

MODBUS客户机接口提供一个接口,使得用户应用能够生成各类MODBUS服务的请求,该服务包括对MODBUS应用对象的访问。

3、MODBUS服务器

收到一个MODBUS请求以后,模块激活一个本地操作进行读、写、或完成其他操作。这些操作的处理对应用程序开发员来说都是透明的。MODBUS服务器的主要功能是等待来自TCP502口的MODBUS请求,处理这一请求,根据设备的现状生成MODBUS应答。

4、MODBUS后端接口

MODBUS后端接口是一个从MODBUS服务器到定义应用对象的用户应用之间的接口。

2.1.3 TCP管理层

报文传输服务的主要功能之一是管理通信的建立和结束,及管理在所建立的TCP连接上的数据流。TCP管理层进行两方面的管理:

1、连接管理

在客户机和服务器的MODBUS模块之间的通信需要TCP管理模块。它负责全面管理报文传输TCP连接。TCP502端口的监听是为MODBUS通信保留的。客户机和服务器均应向用户提供对TCP端口号进行MODBUS参数配置的可能性。

2、访问控制模块管理

在某些至关重要的场合,必须禁止无关的主机对设备内部数据的访问。这既是需要的安全模式,也是在需要时实现安全处理的原因。

2.1.4 TCP/IP栈层

TCP/IP栈提供了一个接口,用来管理连接、发送和接收某些参数配置。TCP连接管理模块采用栈接口,即BSD套接字接口来与TCP/IP栈进行通信。可以对TCP/IP栈进行参数配置,以适用对不同产品或系统的不同特定约束进行数据流控制、地址管理和连接管理。

2.2 两台设备间的通信模型构建

在TCP/IP网络应用中,通信的两个进程相互作用的主要模式是客户机/服务器模式,即客户端向服务器发出请求,服务器接收到请求后提供相应的服务。客户机/服务器模式在操作过程中采取的是主动请求方式。

· 服务器方:首先服务器方要启动,侦听客户方是否有连接请求,并根据请求提供相应服务:a.打开一通信通道并告知本地主机,它愿意在某一公认地址端口上接受客户请求,或者由开发人员自己指定端的地址,此时端口地址应大于1 024B,一般不超过5 000B;b.等待客户请求到达该端口;c.接收到重复服务请求时,处理该请求并发送应答信号。接收并发服务请求,需要激活一个新进程来处理这个客户请求,并不需要对其他请求作出应答。服务完成后,关闭此新进程与客户的通信链路,并终止;d.返回第二步,等待另外的客户请求;e.关闭服务器。

· 客户方:a.打开一通信通道,并连接到服务器所在的主机的特定端口;b.向服务器发出服务请求报文,等待并接收应答;继续提出请求;C,请求结束后关闭通信通道并终止。

从以上描述过程可以看出:客户机与服务器进程的作用是非对称的,因此编码不同,而且服务进程要先于客户请求启动。这个客户机/服务器模型基于4种报

文类型:

MODBUS请求:MODBUS请求是客户机在网络上发送用来启动事务处理的报文。 MODBUS证实:MODBUS证实是在客户机侧接收的响应报文。 MODBUS指示:MODBUS指示是服务器侧接受的请求报文。 MODBUS响应:MODBUS响应时服务器发送的响应报文。 具体模型如下图所示: 请求MODBUS客户机指示响应MODBUS服务器证实 2.3 总体通信模型构建

如下图2、3所示,MODBUS TCP/IP 的通信系统可以包括不同类型的设备: 1、连接至TCP/IP网络的MODBUS TCP/IP客户机和服务器设备。 2、互联设备。 MODBUS客户机串行连接MODBUS客户机TCP/IPMODBUS客户机TCP/IP客户机TCP/IP网关MODBUS TCP/IPMODBUS服务器TCP/IPMODBUS服务器TCP/IP服务器TCP/IP网关MODBUS服务器串机连接MODBUS服务器串机连接MODBUS串行连接

第三章 MODBUS在TCP/IP上的实现与分析

3.1 应用层MODBUS协议描述

3.1.1 TCP/IP上的MODBUS数据应用单元

MODBUS TCP/IP 是在TCP/IP 网络协议加上MODBUS 应用层协议, 形成五层开放式体系结构, 其中MODBUS TCP 数据帧包括报文头、功能代码和数据三个部分, 其结构如图1 所示。

MODBUS TCP/IP ADUMBAP HeaderFunction codePDUMODBUS TCP 数据帧格式

data3.1.2 MBAP报文头描述

MBAP Header 由7 个字节组成,是MODBUS TCP 协议的头部。四个域如图2 所示,Transaction Identifier 为传输标志,Protocol Identifier 为协议标志,Length 是长度域,Unit Identifier 是单元标志。MBAP报文结构如下所示: 2 byteTransaction Identifier2 byteProtocol IdentifierMBAP 报文头结构2 byteLength1 byteUnit Identifier MBAP报文头包括的各个域的功能描述如下表: 域 事务处理标识符 长度 2 byte 描述 MODBUS请求/响应事务处理的识别码 客户机 客户机启动 服务器 服务器从接受的请求中重新复制 协议标识符 2 byte 0=MODBUS协议 客户机启动 服务器从接受的请求中重新复制 长度 2 byte 随后字节的数量 客户机启动 服务器启动(响应) 单元标识符 1 byte 串行链路或其他总线上连接的远程从站的识别 客户机启动 服务器从接受的请求中重新复制

3.2 套接字简介

套接字的概念与文件句柄类似,一个套接字就是一个通信标识,由一个短整数表示,实际上就是一个句柄,代表网络协议中的一组数据,该数据包含了通信双方的IP地址和当前的连接状态等信息。我们知道,如果一个文件被打开,可以通过文件句柄对文件进行读写操作,套接字也一样,只不过套接字提供的函数更多一些。

套接字存在于通信区域中,由协议、地址、端口来描述并惟一确定,根据传输协议的不同,套接字可分为3种类型:流式套接字、数据报套接字和原始套接字。流式套接字提供了一个面向连接的、可靠的、数据无错且按顺序接收的服务,这种套接字对应的是面向连接的传输协议,如TCP/IP协议簇中的TCP。数据报套接字提供了一个无连接服务,不提供无错保证,数据可能丢失或重复,且接受顺序混乱,该套接字所对应的是无连接传输协议,如TCP/IP协议簇中的UDP。原始套接字允许直接访问低层的协议,如IP、ICMP协议,该套接字常用于访问服务器中配置的新设备。

WinSock提供了许多套接字函数,它们并不代表协议的某一个层次,其实质

就是一组编程接口,用户利用这些函数可以很容易地进行编程。该程序设计中用到的套接字如下所示:

(1)socket()函数

Socket()函数用于创建一个套接字。返回的一个套接字号被创建者用来访问该套接字。套接字创建时没有地址(IP地址和端口号)。直到一个端口被绑定到该套接字时,方可接受数据。socket函数用于创建一个套接字。

语法: SOCKET socket ( Int af , Int type, Int protocol );

af:标识一个地址家族,通常为AF_INET。

type:标识套接字类型,如果为SOCK_STREAM,表示流式套接字;如果为SOCK_DGRAM,表示数据报套接字。

protocol:标识一个特殊的协议被用于这个套接字,通常为0,表示采用默认的TCP/IP协议。

(2)bind()函数

Bind()函数用于将套接字绑定到一个已知的地址上。bind()函数在套接字与所指定的端口间建立连接。 语法: int bind (

SOCKET s, const struct sockaddr FAR* name, int namelen );

s:是一个套接字。

name:是一个sockaddr结构指针,该结构中包含了要绑定的地址和端口号。

namelen:确定name缓冲区的长度。

在定义一个套接字后,需要调用bind函数为其指定本机地址、协议和端口号。 例如,创建一个套接字s,将其绑定到502端口上,其代码如下: int port = 502;

SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_IP); sockaddr_in addr;

addr.sin_family = AF_INET; //内部网络协议TCP\\UDP等 addr.sin_port = htons(port); //端口号 addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(s,(LPSOCKADDR)&addr,sizeof(addr))==0) {

MessageBox(\成功\}

(3)connect()函数

为了初始化一个连接,客户机必须发送connect()函数来制定套接字号、远程IP地址和远程监听端口号。语法: int connect (

SOCKET s,

const struct sockaddr FAR* name, int namelen );

s:标识一个套接字。

name:套接字s想要连接的主机地址和端口号。 namelen:name缓冲区的长度。

(4)listen函数

listen函数用于将套接字置入监听模式。 语法: int listen (

SOCKET s, int backlog );

s:套接字。

backlog:表示等待连接的最大队列长度。例如,如果backlog被设置为3,此时有4个客户端同时发出连接请求,那么前3个客户端连接会放置在等待队列中,第4个客户端会得到错误信息。

(5)accept函数

为了完成连接,服务器必须发送accept()函数来指定先前在listen()调用中所指定的套接字号。一个新的套接字被创建,并具有与初始套接字相同的特性。这个新的套接字连接到客户机的套接字,而将套接字号返回到服务器。于是,释放出示套接字,以便为其他欲与该服务器连接的客户机使用。语法: SOCKET accept ( SOCKET s,

struct sockaddr FAR* addr, int FAR* addrlen );

s:是一个套接字,它应处于监听状态。

addr:是一个sockaddr_in结构指针,包含一组客户端的端口号、IP地址等信息。 addrlen:用于接收参数addr的长度。

(6)send()和recv()函数

TCP连接建立以后,数据即可被传送。将send()和recv()函数专门设计成和已经连接的套接字一起使用。

(7)close()函数

一旦不使用,通过该函数关闭套接字。

3.3 应用程序与套接字关系

1、系统调用

大多数操作系统使用系统调用(system call)的机制在应用程序和操作系统之间传递控制权。对程序员来说,每一个系统调用和一般程序设计中的函数调用非常相似,只是系统调用是将控制权传递给了操作系统。如下图所示:

用户地址空间中的应用程序应用程序1应用程序2??应用程序n系统调用接口由应用程序调用的系统函数包括TCP/IP软件协议的操作系统内核系统地址空间中的协议软件

2、应用编程接口 API (Application Programming Interface)

如上图所示,当某个应用进程启动系统调用时,控制权就从应用进程传递给了系统调用接口。操作系统将此接口再将控制权传递给计算机的操作系统。此调用转给某个内部过程,并执行所请求的操作。内部过程一旦执行完毕,控制权就又通过系统调用接口返回给应用进程。

由上可知,系统调用接口实际上就是应用进程的控制权和操作系统的控制权进行转换的一个接口,即应用编程接口 API。套接字(Socket)就是由操作系统提供的一组有关TCP/IP的API1。

3、套接字(Socket)的作用

如下图所示,应用进程通过套接字接入到网络。

由应用程序控制客户应用进程套接字由操作系统控制TCP因特网因特网客户应用进程套接字TCP

第四章

4.1 编程环境 4.1.1 VC++与面向对象

课题的具体实现流程

Windows编程采用的是面向对象的方法(Object Oriented Programming,简称 OOP)。要编写真正的Windows应用程序,就必须对OOP有一定了解。而Visual C++是Windows环境下最主要的开发环境,它支持面向对象编程,并提供可视化编程。

面向对象编程技术不只是一种程序设计的方法,而是客观建立事物模型,分析复杂事物思想的方法。面向对象方法的本质,就是强调从客观事物固有的事物出发来构造系统,用人类常用的思维方式来认、理解和描述事物。

利面向对象的程序设计的核心为: 1、设计思路:对客观事物的抽象。

2、程序特点:对类(对象的存在形式)进行结构化程序设计。 3、类提供简单的对外接口。 面向对象技术的基本特征为:

1、继承性:继承性是指一个新类可以从现有的类中派生出来,新类具有父类中的所有特性,直接继承父类的方法和数据,新类的对象可以调用该类及父类的成员变量和成员函数。

2、封装性:封装性是指把数据和方法放在同一个对象中,对数据的存取只能通过该对象本身的方法来进行。

3、多态性:是指同一消息被不同的对象界首市,可以解释为不同意义的能力,会产生不同的行为。

4.1.2 Visual C++ /MFC开发程序

库(library)是可以重复使用的源代码和目标代码的集合。MFC(Microsoft

Fundamental Classes)是Visual C++开发环境所带的类库,在该类库中提供了大量的类,可以帮助开发人员快速建立应用程序。这些类可以提供程序框架、进行

文件和数据库操作、建立网络连接、进行绘图和打印等各种通用的应用程序操作。使用MFC库开发应用程序可以减少很多工作量。

MFC借助C++的优势为Windows开发开辟了一片新天地,同时也借助

ApplicationWizzard使开发者摆脱离了那些每次都必写基本代码,借ClassWizard2和消息映射使开发者摆脱了定义消息处理时那种混乱和冗长的代码段。更令人兴奋的是利用C++的封装功能使开发者摆脱Windows中各种句柄的困扰,只需要面对C++中的对象,这样一来使开发更接近开发语言而远离系统。

4.2 编程语言

正因为MFC是建立在C++的基础上,所以我强调C/C++语言基础对开发的重要性。利用C++的封装性开发者可以更容易理解和操作各种窗口对象;利用C++的派生性开发者可以减少开发自定义窗口的时间和创造出可重用的代码;利用虚拟性可以在必要时更好的控制窗口的活动。而且C++本身所具备的超越C语言的特性都可以使开发者编写出更易用,更灵活的代码。现在C++由以下四个\子语言\组成:

1、C子语言。C++支持C语言的几乎全部功能,在语法上与C语言仅有极微妙的差别。

2、面向对象的C++。C++首先作为一门面向对象的语言而闻名,这个特点在这里不再详述。

3、泛型编程语言。C++强大模板功能使它能在编译期完成许多工作,从而大大提高运行期效率。

4、STL3。随着STL的不断发展,它已经逐渐成为C++程序设计中不可或缺的部分,其效率可能比一般的na?ve代码低些,但是其安全性与规范性使它大受欢迎。

4.3 套接字实现流程

1 、 套接字工作原理

(1) 当应用进程需要使用网络进行通信时就发出系统调用,请求操作系统为其创建“套接字”,以便把网络通信所需要的系统资源分配给该应用进程。

(2) 操作系统为这些资源的总和用一个叫做套接字描述符的号码来表示,并把此号码返回给应用进程。应用进程所进行的网络操作都必须使用这个号码。 (3) 通信完毕后,应用进程通过一个关闭套接字的系统调用通知操作系统回收与该“号码”相关的所有资源。

2、 创建套接字

服务器端:当套接字被创建后,它的端口号和 IP 地址都是空的,因此应用进程要调用 bind(绑定)来指明套接字的本地地址。例如,在服务器端调用 bind 时就是把熟知端口号和本地IP地址填写到已创建的套接字中。这就叫做把本地地址绑定到套接字。服务器在调用 bind 后,还必须调用 listen(收听)把套接字设置为被动方式,以便随时接受客户的服务请求。UDP4服务器由于只提供无连接服务,不使用 listen 系统调用。服务器紧接着就调用 accept(接受),以便把远地客户进程发来的连接请求提取出来。系统调用 accept 的一个变量就是要指明从哪一个套接字发起的连接。具体的服务器端进程如下所示:

if(! AfxSocketlnit()){

MessageBox(“WindowsSocket initial failed!”,“Send”, MB—ICONSTOP); Return;

}//套接字初始化

CSocket ChatSend,Server;//构造2个套接字对象,nPort是socket的端口号。 if(!Chatsend.Create(nPort)){//初始化socket.

MessageBox ( “SendSocket create failed!”, MB—ICONSTOP); Return ; else

ChatSend.Bind(nPort,strAddr);//把本地址和socket绑定,其中nPort是socket的端口号,strAddr是机器的IP地址。 ChatSend.Listen();//开始侦听

ChatSend.Accept(server);//新的套接字上接收客户端socket连接 }

Server.SendTo(csSendText.csCount,nPurt,strAddr);//发送一个字符串 Server.close();//关闭这2个socket

ChatSend Close();

流程:文字改成程序流程图

客户端:它比较简单,第一,创建套接字socket,第二,通过connect函数向服务器发出连接请求,然后就可以通过send,recv函数发送和接收信息了。具体客户端进程代码如下所示: if(!AfxSocketlnit()){

MessageBox( “WindowsSocket initial failed!” , “Receive”,MB—ICONSTOP); Return;

}//套接字初始化

bcket ChatReceive;//构建一个Socket对象 if(!ChatReceive.Geste(nPort)){//初始化socket.

MessageBox(“Receive.Socket create failed !” , “Receive”,MB—ICONSTOP); Return; }

else{ChatReceive.Connect(strAd&,nPort);//建立和服务器的连接 }

ChatReceive.ReceiveFrcgn(csReceiveText,csCount,strAddr,n-Port);//接收字符串

ChatReceive.Close();//关闭套接字socket

4.4 MODBUS协议编程实现

(一)通讯口设置 DCB dcb;

hCom=CreateFile(\

GENERIC_READ|GENERIC_WRITE, 0,

NULL,

OPEN_EXISTING, 0, NULL);

if(hCom==INVALID_HANDLE_VALUE) {

MessageBox(\}

BOOL error=SetupComm(hCom,1024,1024); if(!error)

MessageBox(\error=GetCommState(hCom,&dcb); if(!error)

MessageBox(\dcb.BaudRate=2400; dcb.ByteSize=8;

dcb.Parity=EVENPARITY;//NOPARITY; dcb.StopBits=ONESTOPBIT; error=SetCommState(hCom,&dcb); (二)CRC校验码计算 UINT crc

void calccrc(BYTE crcbuf) { BYTE i; crc=crc ^ crcbuf; for(i=0;i<8;i++)

{ BYTE TT; TT=crc&1; crc=crc>>1; crc=crc&0x7fff; if (TT==1) crc=crc^0xa001; crc=crc&0xffff; } }

(三)数据发送

zxaddr=11;//读取地址为11的巡检表数据 zxnum=10;//读取十个通道的数据 writebuf2[0]=zxaddr; writebuf2[1]=3; writebuf2[2]=0; writebuf2[3]=0; writebuf2[4]=0; writebuf2[5]=zxnum; crc=0xffff;

calccrc(writebuf2[0]); calccrc(writebuf2[1]); calccrc(writebuf2[2]); calccrc(writebuf2[3]); calccrc(writebuf2[4]); calccrc(writebuf2[5]);

writebuf2[6]=crc & 0xff; writebuf2[7]=crc/0x100;

WriteFile(hCom,writebuf2,8,&comnum,NULL); (四)数据读取

ReadFile(hCom,writebuf,5+zxnum*2,&comnum,NULL); //读取zxnum个通道数据 可增加错误处理程序,如地址码错误、CRC码错误判断、通讯故障处理等。

第五章 对程序实现结果的分析

5.1 程序实现结果演示

该课题的实现包括客户端和服务器两部分,而两部分的实现有异曲同工之

妙,由于都是采用嵌入MODBUS协议的应用层,在MODBUS编程上没有差异。客户端和服务器的差异主要体现在套接字上。因为该模型要求服务器端完成更多的工作,包括端口的绑定和监听,而客户端只是得到端口号并建立连接。只要掌握了服务器端的实现,则整个课题能够得到很快的解决,服务器端的实现界面如下所示:

5.2 对MODBUS TCP/IP 报文的分析

为了更清楚的了解协议通信规程, 表1 给出了用Ethereal捕获的MODBUS TCP 原始通信报文。在表1 中, 9个包是写单个寄存器命令,单次完成一个命令操作通信双方需交换9个数据包, 基中前三个包完成TCP 连接, 后续二个包完成命

令操作的请求和响应, 最后4个包完成TCP 的关闭。在实际工作中, 为了提高通信效率, 往往一次连接上完成多个命令的数据交换。表1如下所示:

No 1 2 3 4 Source 172.16.1.2 172.16.1.1 172.16.1.2 172.16.1.2 Destination 172.16.1.1 172.16.1.2 172.16.1.1 172.16.1.1 Protocol Info TCP 3047>502[SYN]Seq=0 Ack=0 Win=65535 Len=0 MSS=1460 TCP 502>3047[SYN,ACK]Seq=0 Ack=1Win=65535Len=0MSS=1400 TCP 3047>502[ACK]Seq=1Ack=1Win=65535Len=0 MODBUS/TCP query[1pkt(s)]:trans: 0;until: 1,func: 6,Write single register 5 172.16.1.1 172.16.1.2 MODBUS/TCP response[1pkt(s)]:trans: 0;until: 1,func: 6,Write single register 6 7 8 9 172.16.1.2 172.16.1.1 172.16.1.1 172.16.1.2 172.16.1.1 172.16.1.2 172.16.1.2 172.16.1.2 TCP 3047>502[FIN,ACK]Seq=13Ack=13 Win=65523 Len=0 TCP 502>3047[ACK]Seq=13 Ack=14 Win=65523Len=0 TCP 502>3047[FIN,ACK]Seq=13 Ack=14 Win=65523 Len=0 TCP 3047>502[ACK]Seq=14Ack=14 Win=65523 Len=0

MODBUS TCP/IP 是建立在TCP/IP 网络协议之上的, 对该协议进行数据分析, 有利于进一步了解协办的内部结构, 便于正确理解和熟练运用。下面以表1 中的4 号和5 号包为例进行分析。4号包为Master 端向Slave端发的MODBUS请求, 66 个字节, 5 号包为Slave对4号包的响应, 也是66 字, 包含了MODBUS TCP/IP 五层协议的数据, 各字段的意义如下:

0000 00 1b fc b9 b4 92 00 e0 4c 00 01 f9 08 00 45 00 ① ② ③

0010 00 34 0e 39 40 00 80 06 92 67 ac 10 01 02 ac 10 ④

0020 01 01 0b e7 01 f6 b5 78 ef d6 90 4c eb 18 50 18

0030 ff ff 25 9b 00 00 00 00 00 00 00 06 01 06 00 00

0040 00 64

0000 00 e0 4c 00 01 f9 00 1b fc b9 b4 92 08 00 45 00

① ② ③

0010 00 34 05 79 40 00 80 06 9b 27 ac 10 01 01 ac 10

0020 01 02 01 f6 0b e7 90 4c eb 18 b5 78 ef e2 50 18

0030 ff f3 25 9b 00 00 00 00 00 00 00 06 01 06 00 00

⑥ ⑦

0040 00 64

其中:①号字段②号字段为以太网的物理地址, ③字段为上层协议标志为IP 协议, 网络接口层使用的是Ethernet II 帧格式; ④字段为IP 层数据, 分别为协议版本、服务类型、头长度( 20 字节) 、传输不分片、存活时间、上层协议( TCP) 、头校验和、目的IP 和源IP 地址; ⑤字段为TCP 层数据, 分别为源端、目的端口、数据报序号、滑动窗口大小和校验和; ⑥号字段、⑦字段为MODBUS协议数据, 其中⑥号字段为MBAP 报文头, 传输标志为0X0000, 协议标志为0X0000, 长度为0X0006, 单元标志为0 X01 即1 号寄存器, ⑦字段为MODBUS的PDU, 功能代码为0X06(写单个寄存器), 起始地址为0X0000, 写入的数据为0X0064。

第六章 总结与展望

6.1 总结

基于TCP/IP的MODBUS通信协议模型,数据链路层协议和物理层协议就是以太网标准中规定的那些协议,如IEEE802.3。网络层采用IP协议,传输层采用TCP协议。TCP协议是面向连接的,它通过三次握手提供可靠的数据报传送

服务。而应用层则采用MODBUS协议。MODBUS协议由美国著名的自动化设备制造商莫迪康公司开发,是应用于自动控制器上的一种通用协议。通过此协议,控制器相互之间、控制器经由网络(例如以太网)和其它设备之间可以通信。它已经成为一种通用工业标准。MODBUS协议是一种主从协议,网段的一个节点被指定为主节点,其他节点为从节点。为保证每个节点都有机会传送数据,主节点通常对从节点依次逐一的轮询,形成严格的周期性报文传输,它还允许一台主机和一个或多个从机通讯,以完成编程、数据传送及程序下载等功能。由于TCP/IP协议的复杂性,本文程序用VC中的套接字实现网络接口。套接字是一种标准API,主要用于网络中的数据通信,它允许两个或者多个应用程序在同一台机器上或网络相互通信。使用套接字编程接口,应用程序可通过普通网络协议如TCP/IP,或IPX协议建立通信。

MODBUS TCP/IP协议适合于一台主机和多个从设备的环境中,主机访问

从设备的方法采用轮询的方法,即按照从设备1,从设备2,…..从设备n的顺序依次访问,一次访问结束后,再从头开始。有人认为这样做会降低效率,的确,这种轮询的方法不如MODBUS Plus多主访问模式的效率高,但这种轮询的方式也有它的优点,那就是用上层协议的确定性消除了下层协议的不确定性。MODBUS具有众多优点,所以成为一种广泛应用的工业协议。

6.2 展望

MODBUS/TCP是真正通过Ethernet TCP/IP途径的MODBUS。它使用与MODBUS同样的寄存器和位表示法,它还使用为MODBUS定义的同样函数。所有MODBUS消息和MODBUS /TCP消息是一致的,只是后者未包括循环冗余码校验(CRC)字段。任何有能力研发MODBUS /TCP网络设备人员也能研发MODBUS /TCP。协议的实施极其快速,非常适合专用诊断和配置应用。MODBUS的简明性既是它的最大优点,也是它的最大缺点。虽然容易明了和快速实施,MODBUS /TCP缺少标准化。一个供应商的MODBUS /TCP 产品和另一个供应商的产品截然不同。用户可从因特网上下载免费的MODBUS /TCP依从性测试程序。

MODBUS/TCP协议已经被广泛运用于各个行业,但谈起MODBUS协议的

发展未来,我认为与工业以太网的发展密不可分。工业以太网技术是当前工业控制领域中的研究热点,多家自动化公司已推出了自己的工业以太网解决方案。通过对典型的工业以太网的分析,不难发现,每一种工业以太网都有其互补的现场总线,如MODBUS-IDA与MODBUS互补;PROFINET与PROFIBUS互补等,而现场总线经过十几年的发展,在技术上日渐成熟,工业以太网的发展是与现场总线相结合的。目前,在控制网络中,一般是在设备层采用现场总线,在制造执行层与设备层之间采用工业以太网,这样既减少了用户的投资风险,又保护了用户的已有设备和技术投资。另外值得一提的是,工业以太网正逐渐向现场I/O扩展,逐渐替代现场总线,如西门子推出的PROFINET I/O产品。

我国也在进行工业以太网标准的研究和制定,EPA(Ethernet for Plant Automation)就是在国家“863”课题的支持下,由浙江大学、浙大中控和中科院沈阳自动化所等多家单位联合攻关,在解决多项关键技术的基础上起草的我国第一个拥有自主知识产权的工业以太网国家标准,它是从我国国情研发的国家标准,相信在今后的工业控制领域占有一席之地。随着工业以太网的发展,应用于工业以太网的MODBUS/TCP也会在未来的领域占有一席之地。

注释:

1

林永. windows API编程手册[M].北京:人民邮电出版社,2002:107

234

候捷.深入浅出MFC[M].武汉:华中科大出版社,2001:34

葛建芳.c++标准模板库与代码重用[J].南通大学学报(自然科学版).2006,2006 5(2):7 曹伟.TCP/IP协议实现[J].辽宁学院学报(自然科学版).2009,2009 16(1):6

参考文献:

[1] 缪学勤.工业以太网技术的现状与发展.世界仪表与自动化,2003(10)

[2] 科默 D E (Comer,Douglas E)著 用TCP/IP进行网际互联— 第三卷—客户/服务器编程与应用[M]。 北京:电子工业出版社。1999

[3]Anthony Jones. Window 网络编程技术[M]。北京:机械工业出版社。1999 [4] 李凌 著 Winsock2 网络编程实用教程[ M ] 。北京:清华大学出版社。2003

[5]MODBUS.ORG:MODBUS Application Protocol Specification.兰州理工大学电气工程及信息工程学院施耐德实验室

[6]Andy Swales,OPEN MODBUS/TCP SPECIFICATION, SchneiderElectric, 1999(3) [7] 孙海民,Windows Sockets网络开发[M],北京:人民邮电出版社,2008.7

[8] 曹衍龙,Visual C++网络通信编程实用案例精选[M],北京:人民邮电出版社,2007.9 [9] 孙鑫,VC++深入详解[M],北京:电子工业出版社,2006.6 [10] Tony Cardiello.MODBUS: The Open Protocol Over TCP/IP[M].2002.3 [11] Market Routes. MODBUS TCP: An Open Way Forward[M].2002.4 [12] Tony Cardiello.MODBUS Supports Web Developments[M].2002.7 附录:

#include \

#include \#include \#include \#include \#include \#ifdef _DEBUG

#define new DEBUG_NEW #undef THIS_FILE

static char THIS_FILE[] = __FILE__; #endif

///////////////////////////////////////////////////////////////////////////// // CModbusClientApp

BEGIN_MESSAGE_MAP(CModbusClientApp, CWinApp) //{{AFX_MSG_MAP(CModbusClientApp) ON_COMMAND(ID_APP_ABOUT, OnAppAbout)

// NOTE - the ClassWizard will add and remove mapping macros here.

// DO NOT EDIT what you see in these blocks of generated code!

//}}AFX_MSG_MAP

// Standard file based document commands

ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) // Standard print setup command

ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) END_MESSAGE_MAP()

///////////////////////////////////////////////////////////////////////////// // CModbusClientApp construction

CModbusClientApp::CModbusClientApp() { // TODO: add construction code here, }

// Place all significant initialization in InitInstance

///////////////////////////////////////////////////////////////////////////// // The one and only CModbusClientApp object

CModbusClientApp theApp;

///////////////////////////////////////////////////////////////////////////// // CModbusClientApp initialization

BOOL CModbusClientApp::InitInstance() { AfxEnableControlContainer();

#ifdef _AFXDLL Enable3dControls();

// Call this when using MFC in a shared DLL

// Standard initialization

// If you are not using these features and wish to reduce the size

// of your final executable, you should remove from the following // the specific initialization routines you do not need. if (!AfxSocketInit()) { }

AfxMessageBox(IDS_SOCKETS_INIT_FAILED); return FALSE;

#else

Enable3dControlsStatic();

// Call this when linking to MFC statically

#endif }

// Change the registry key under which our settings are stored.

// TODO: You should modify this string to be something appropriate

// such as the name of your company or organization. SetRegistryKey(_T(\

LoadStdProfileSettings(); // Load standard INI file options (including MRU) // Register the application's document templates. Document templates // serve as the connection between documents, frame windows and views. CSingleDocTemplate* pDocTemplate; pDocTemplate = new CSingleDocTemplate( IDR_MAINFRAME,

RUNTIME_CLASS(CDocumentHelper),

RUNTIME_CLASS(CMainFrame), // main SDI frame window

RUNTIME_CLASS(CClientsComView)); AddDocTemplate(pDocTemplate);

// Parse command line for standard shell commands, DDE, file open CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo);

// Dispatch commands specified on the command line if (!ProcessShellCommand(cmdInfo)) return FALSE;

// The one and only window has been initialized, so show and update it. m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); return TRUE;

///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About

class CAboutDlg : public CDialog {

public: CAboutDlg();

// Dialog Data

//{{AFX_DATA(CAboutDlg)

enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA

// ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg)

protected:

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //}}AFX_VIRTUAL

// Implementation

protected: //{{AFX_MSG(CAboutDlg) // No message handlers //}}AFX_MSG DECLARE_MESSAGE_MAP() };

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { }

void CAboutDlg::DoDataExchange(CDataExchange* pDX) { }

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP()

// App command to run the dialog

void CModbusClientApp::OnAppAbout() { }

CAboutDlg aboutDlg; aboutDlg.DoModal();

CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT

///////////////////////////////////////////////////////////////////////////// // CModbusClientApp message handlers

BOOL CModbusClientApp::PreTranslateMessage(MSG* pMsg) { }

// TODO: Add your specialized code here and/or call the base class CMainFrame *pFrame = (CMainFrame*)AfxGetMainWnd(); if (pFrame) {

if (pFrame->m_Framework.ProcessMessage(pMsg))

return TRUE;

}

return CWinApp::PreTranslateMessage(pMsg);

///////////////////////////////////////////////////////////////////////////// // CModbusClientApp message handlers

BOOL CModbusClientApp::PreTranslateMessage(MSG* pMsg) { }

// TODO: Add your specialized code here and/or call the base class CMainFrame *pFrame = (CMainFrame*)AfxGetMainWnd(); if (pFrame) {

if (pFrame->m_Framework.ProcessMessage(pMsg))

return TRUE;

}

return CWinApp::PreTranslateMessage(pMsg);

本文来源:https://www.bwwdw.com/article/7eaa.html

Top