基于VC++的串口通信服务的开发 精品.doc_第1页
基于VC++的串口通信服务的开发 精品.doc_第2页
基于VC++的串口通信服务的开发 精品.doc_第3页
基于VC++的串口通信服务的开发 精品.doc_第4页
基于VC++的串口通信服务的开发 精品.doc_第5页
已阅读5页,还剩15页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基于VC+的串口通信服务的开发1 引言1.1 课题背景计算机与外界的信息交换称为通信。基本的通信方式有并行通信和串行通信两种。串行通信是指一条信息额各位数据被逐位按顺序传送的通信方式。串行通信的特点是:数据位传送,按位顺序进行,最少只需要一根传输线即可完成,成本低但传送速度慢。串行通信的距离可以从几米到几千米。1.2 研究现状串口通讯目前流行的方法大概有三种:一是利用Microsoft提供的CMSM控件进行通讯,不过现在很多程序员都觉应该放弃这种方式。二是利用WINAPI函数进行编程,这种编程的难度高,要求掌握很多的API函数。三是利用现在网络上面提供的一些串口通讯控件进行编写。这三种方法都没有同Windows服务联系起来。1.3 研究的意义利用串口进行数据通讯在通讯领域中占有着重要的地位,串口通讯在通讯软件中有着十分广泛的应用。如电话、传真、视频和各种控制等。通过本文的研究和开发能更加方便的通过网络通信来实现串口通信,提高串口的利用率。为进一步的研究提供参考。2 相关理论基础2.1 Windows NT 服务有那么一类应用程序,是能够为各种用户(包括本地用户和远程用户)所用的,拥有用户授权级进行管理的能力,并且不论用户是否物理的与正在运行该应用程序的计算机相连都能正常执行,这就是所谓的服务了。每个操作系统都需要有在后台执行任务的方法,无论是谁正在使用这部机器,这些任务都可以继续运行,后台任务可以处理各种重要的服务,包括系统的或者用户的。在Windows NT中,后台的任务被称为服务。服务可在每次NT启动的时候运行,并且不管是谁登陆,都会一直运行下去。服务是一类受到操作系统优待的程序。一个服务首先是一个Win32可执行程序,通常以控制台程序的形式被编写,进入点函数是Main()而不是WinMain()。一个Windows NT服务由三部分组成,第一部分是Service Control Manager(SCM)。每个Windows NT/2000系统都有一个SCM,SCM存在于Service.exe中,在Windows启动的时候会自动运行,伴随着操作系统的启动和关闭而产生和终止。这个进程以系统特权运行,并且提供一个统一的、安全的手段去控制服务。它其实是一个RPC Server,因此我们可以远程安装和管理服务,不过这不在本文讨论的范围之内。SCM包含一个储存着已安装的服务和驱动程序的信息的数据库,通过SCM可以统一的、安全的管理这些信息,因此一个服务程序的安装过程就是将自身的信息写入这个数据库。第二部分就是服务本身。一个服务拥有能从SCM收到信号和命令所必需的特殊代码,并且能够在处理后将它的状态回传给SCM。第三部分也就是最后一部分,是一个服务控制管理器(Service Control Dispatcher,SCP)。它是一个拥有用户界面,允许用户开始、停止、暂停、继续,并且控制一个或多个安装在计算机上服务的Win32应用程序。SCP的作用是与SCM通讯,Windows 2000管理工具中的“服务”就是一个典型的SCP。2.2 串口通信串行口是计算机一种常用的接口,具有连接线少,通讯简单,得到广泛的使用。常用的串口是 RS-232-C 接口(又称 EIA RS-232-C)它是在 1970 年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标准。它的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准”该标准规定采用一个 25 脚的 DB25 连接器,对连接器的每个引脚的信号内容加以规定,还对各种信号的电平加以规定。传输距离在码元畸变小于 4% 的情况下,传输电缆长度应为 50 英尺。典型地,串口用于ASCII码字符的传输。通信使用3根线完成:地线,发送线,接收线。由于串口通信是异步的,端口能够在一根线上发送数据同时在另一根线上接收数据。其它线则用于硬件握手,但是不是必须的。串口通信最重要的参数是波特率、数据位、停止位和奇偶校验。对于两个进行通行的端口,这些参数必须匹配:波特率:这是一个衡量通信速度的参数。它表示每秒钟传送的bit的个数。例如300波特表示每秒钟发送300个bit。当我们提到时钟周期时,我们就是指波特率例如如果协议需要4800波特率,那么时钟是4800Hz。这意味着串口通信在数据线上的采样率为4800Hz。通常电话线的波特率为14400,28800和36600。波特率可以远远大于这些值,但是波特率和距离成反比。高波特率常常用于放置的很近的仪器间的通信,典型的例子就是GPIB设备的通信。数据位:这是衡量通信中实际数据位的参数。当计算机发送一个信息包,实际的数据不会是8位的,标准的值是5、7和8位。如何设置取决于你想传送的信息。比如,标准的ASCII码是0127(7位)。扩展的ASCII码是0255(8位)。如果数据使用简单的文本(标准 ASCII码),那么每个数据包使用7位数据。每个包是指一个字节,包括开始/停止位,数据位和奇偶校验位。由于实际数据位取决于通信协议的选取,术语“包”指任何通信的情况。停止位:用于表示单个包的最后一位。典型的值为1,1.5和2位。由于数据是在传输线上定时的,并且每一个设备有其自己的时钟,很可能在通信中两台设备间出现了小小的不同步。因此停止位不仅仅是表示传输的结束,并且提供计算机校正时钟同步的机会。适用于停止位的位数越多,不同时钟同步的容忍程度越大,但是数据传输率同时也越慢。奇偶校验位:在串口通信中一种简单的检错方式。有四种检错方式:偶、奇、高和低。当然没有校验位也是可以的。2.3 多线程及线程间通信进程(Process)是具有一定独立功能的程序关于某个数据集合上的一次运行活动,是系统进行资源分配和调度的一个独立单位。程序只是一组指令的有序集合,它本身没有任何运行的含义,只是一个静态实体。进程则不同,它是程序在某个数据集上的执行,是一个动态实体。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤消,反映了一个程序在一定的数据集上运行的全部动态过程。线程(Thread)是进程的一个实体,是CPU调度和分派的基本单位。线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。线程和进程的关系是:线程是属于进程的,线程运行在进程空间内,同一进程所产生的线程共享同一内存空间,当进程退出时该进程所产生的线程都会被强制退出并清除。线程可与属于同一进程的其它线程共享进程所拥有的全部资源,但是其本身基本上不拥有系统资源,只拥有一点在运行中必不可少的信息(如程序计数器、一组寄存器和栈)。线程带来的主要好处是:在进程内创建、终止线程比创建、终止进程要快;同一进程内线程间的切换要比进程间的切换要快,尤其是用户级线程间的切换。另外,线程的出现还因为以下几个原因:并发程序的并发执行,在多处理环境下更为有效。一个并发程序可以建立一个进程,而这个并发程序中的若干并发程序段就可以分别建立若干线程,使这些线程在不同的处理机上执行。每个进程具有独立的地址空间,而该进程内的所有线程共享该地址空间。这样可以解决父子进程模型中,子进程必须复制父进程地址空间的问题。线程对解决客户/服务器模型非常有效。线程之间通信的两个基本问题是互斥和同步。线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。线程互斥是指对于共享的操作系统资源(指的是广义的“资源”,而不是Windows的.res文件,譬如全局变量就是一种共享资源),在各线程访问时的排它性。当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。线程互斥是一种特殊的线程同步。实际上,互斥和同步对应着线程间通信发生的两种情况:当有多个线程访问共享资源而不使资源被破坏时;当一个线程需要将某个任务已经完成的情况通知另外一个或多个线程时。在WIN32中,同步机制主要有以下几种:事件(Event);信号量(semaphore);互斥量(mutex);临界区(Critical section)。2.4 安全队列队列(Queue)在计算机科学中,是一种先进先出的线性表。和栈相反,它只允许在表的一端进行插入,而在表的另一端删除元素。队列是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。进行插入操作的端为队尾,进行删除操作的端为队头。队列中没有元素时,称为空队列。在用链式存储结构表示队列时,需要设置队列头指针和队列尾指针,以便指示队列头结点和队列尾结点。安全队列是指高级队列的代理明确指出一个或多个数据库用户可以对队列进行操作。安全队列的拥有者可以执行所有的队列操作,而其他用户除非被配置为这个安全队列的安全队列用户,否则不能对这个安全队列执行操作。安全队列在队列的入队和出队操作时的各线程同步。在某一时刻只能有一个线程操作该队列,这样的队列就是安全的队列。把队列的队头视为临界区,要对队列进行操作需进入临界区,从而实现现成的同步,队列的安全。2.5 Windows套接字规范随着个人计算机的日益普及,Windows操作系统的用户与日俱增。Microsoft以Berkeley Socket规范为范例定义了一套Microsoft Windows下的网络编程接口,它不仅包含了人们很熟悉的Berkeley Socket风格的库函数,也包含了一组针对Windows的扩展库函数,一是程序员能充分利用Windows消息驱动机制进行编程。Windows Socket规范本意在于提供给应用程序开发者一套简单的API,并让各家网络软件供应商共同遵守。此外,在一个特定版本Windows的基础上,Windows Socket规范也定义了一个二进制接口(ABI),并通过此二进制接口来保证其兼容性。因此这份规范定义了应用程序开发者能够使用,而且网络软件供应商也能够实现的一套函数调用和相关语义。遵守这套Windows Socket规范的网络软件,称之为Windows Socket兼容,而Windows Socket兼容实现的提供者,称之为Windows Socket提供者。一个网络软件供应商必须百分之百地实现Windows Socket规范才能做到Windows Socket兼容。Windows Socket规范定义并记录了如何使用API与Internet协议相连接,尤其要指出的是,所有的Windows Socket实现都支持流式套接字和数据报套接字。应用程序调用Windows套接字的API实现相互之间的通信。Windows套接字有利用下层的网络通信协议功能和操作系统调用实现实际的通信工作。在TCP/IP网络中两个进程间的相互作用的主机模式是客户机/服务器模式(Client/Server model)。该模式的建立基于以下两点:非对等作用和异步通信。客户机/服务器模式在操作过程中采取的是主动请示方式。首先服务器方要先启动,并根据请示提供相应服务:打开一个通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请求;等待客户请求到达该端口;接收到重复服务请求,处理该请求并发送应答信号;返回第二步,等待另一客户请求;关闭服务器。客户方:打开一个通信通道,并连接到服务器所在主机的特定端口;向服务器发送服务请求报文,等待并接收应答;继续提出请求;请求结束后关闭通信通道并终止。Windows Socket 2.0是Windows Socket 1.1发展的一个比较重大的变革,为了能与Windows Socket 1.1实现很好的兼容性,它在这基础上做了向后兼容:源码和二进制代码。这就实现了Windows Socket应用程序和任何版本的Windows Socket实现之间的最大的互操作性,同时也减少了Windows Socket应用程序使用者、网络协议栈提供者和服务提供者的许多痛苦。2.6 客户机服务器系统客户机服务器系统(ClientServer System)是计算机网络(尤其是Internet)中最重要的应用技术之一,其系统结构是指把一个大型的计算机应用系统变为多个能互为独立的子系统,而服务器便是整个应用系统资源的存储与管理中心,多台客户机则各自处理相应的功能,共同实现完整的应用。用户使用应用程序时,首先启动客户机通过有关命令告知服务器进行连接以完成各种操作,而服务器则按照此请示提供相应的服务。这是网络软件运行的一种形式。通常,采用客户机服务器结构的系统,有一台或多台服务器以及大量的客户机。服务器配备大容量存储器并安装数据库系统,用于数据的存放和数据检索;客户端则安装专用的软件,负责数据的输入、运算和输出。客户机和服务器都是独立的计算机。当一台连入网络的计算机向其他计算机提供各种网络服务(如数据、文件的共享等)时,它就被叫做服务器。而那些用于访问服务器资料的计算机则被叫做客户机。严格说来,客户机服务器模型并不是从物理分布的角度来定义,它所体现的是一种网络数据访问的实现方式。采用这种结构的系统目前应用非常广泛。如宾馆、酒店的客房登记、结算系统,超市的POS系统,银行、邮电的网络系统等。计算机网络的主要用途之一是允许共享资源。这种共享是通过相呼应的两个独立程序来完成的。每个程序在相应的计算机上运行。一个程序在服务器中,提供特定资源;另一个程序在客户机中,它使客户机能够使用服务器上的资源。例如,你正在计算机上用一个文字处理程序(如Word)进行工作,你告诉程序,你要编辑一个存贮在网络的另一台计算机中的特定的文件。你的程序将给那台计算机发送一个信号,请求它把这个文件传输过来。在这种情况下,你的文字处理程序是客户机,此时接受这种请求并发出这个文件的程序叫服务器,更确切地说它是一个文件服务器。 这种系统的绝妙之处,就是客户机和服务器程序不在同一台计算机上运行,这些客户机和服务器程序通常归属不同的计算机。例如,你可能坐在中国北京的一台PC机前,通过来阅读万里之外的美国国家安全局的“今日新闻”,看一看美国总统选举的闹剧。在这种情况下,客户机就是你的PC机,它运行着一个程序,此时服务器是在美国另一端的一台超级计算机,它运行着另一个程序。大部分计算机网络(包括所有的Internet服务)都使用这种客户机服务器关系。要懂得怎样使用计算机网络(尤其是Internet),事实上就意味着要懂得怎样使用每个客户机程序。你的任务是启动客户机,并叫它执行程序。客户机的任务是连接上相对应的服务器,并确保你的指令正确执行。客户机服务器工作时通常由一个公共的规制需要遵守,通信双方需要共同遵守这个规则才能保证通信的有效性,如需要传输大量语音数据时,需采用一种无须建立连接的传输方式,在这种方式下,数据可以以较快的熟读传输,而当需要确保数据准确无误地到达时,则应采用另外一种面向连接的传输方式。3 需求分析及设计方案3.1 功能需求3.1.1 服务器端串口服务器上的串口通信服务打开一个固定的端口,监听客户端的Socket连接。若检测到客户端的连接则为客户端分配一个串口,供客户端发送数据。客户端同服务器协商好串口的配置信息,则客户端发送的数据服务器直接发送到串口,通过串口发送除去。若服务器检测到串口接受到数据,者直接把接收到的数据发送到客户端。即服务器中转串口和客户端的数据。这样一来客户端就好像直接链接到串口服务器上的串口,与服务器串口相连接的外设进行通信。串口服务器具有很多个串口形成一个串口池。串口池中的串口连接着不通或相同的外设,客户通过Internet联网的方式链接到服务器,同服务器的外设通信。3.1.2 串口通信串口通信服务管理整个串口池。服务程序对串口池进行合理管理和分配,服务器端接收到客户端的连接请求,服务器会从串口池中选取一个串口供客户端使用。当客户端通信完毕,断开同服务器的链接时,服务器端回收这个串口,以供其他客户端使用。在分配串口的时候不能让不同用户使用同一串口,让每一个客户端独立的使用某一个串口。当客户端链接上服务器后,服务器为客户端分配一个串口供客户端使用。这时候串口通信需要被实现。包括串口的打开,串口参数设置,读写数据到串口以及关闭串口。3.1.3 客户端客户端的需求相对简单。连接服务器的客户端通过指定服务器地址和端口号连接到服务器,设置串口的通信参数,同服务器通信。可以发送数据到服务器和接受服务器发送回来的数据,并显示接收到的数据。通信完毕时断开通服务器的连接。3.2 设计方案3.2.1 服务器端服务器端使用Windows NT服务来提供服务,此服务监听某一端口,等待客户端的链接。为客户端提供服务。使用Windows API自己定义服务的行为。服务管理串口池,服务启动初始化时,检测服务器的串口,串口统一进入一个全局安全队列。当客户端发起连接请求时,服务器开启一个线程来处理该客户的请求,直到客户端断开连接,线程退出执行。在线程中,从安全队列的队头出队列一个串口,该串口分配给该客户使用,客户端首先设置该串口的通信参数,否则按照默认串口通信参数进行通信。如果有多个客户同时连接服务器则服务器同时开启多个线程来处理多个用户的连接请求。分配给客户端使用的串口接收外设发来数据时,服务器通过连接的Socket发送到客户端,客户端处理接收到的数据。服务器端接收到客户端发来的数据时,把接收到的数据发送到分配给这个客户端的串口,通过串口发送到外设,外设处理接收到的数据从而做出反应,完成通信。3.2.2 串口通信使用Windows API的串口操作函数,封装成串口类,来处理串口通信。此串口类统一操作串口池里的串口,根据不同的串口号来操作这些串口。从而达到每一个客户的使用一个串口,每个串口都是相同的操作。可以根据不同的通信设备为不同的串口设置不同的通信参数。串口通信负责处理串口的参数设置,串口的打开和关闭,数据的读和写,即写数据到串口和从串口读数据。打开串口时,服务处理此客户的线程开启另一线程监听串口是否有数据接收,当发现有数据来的时候,串口读出该数据通过Socket发送到客户端。3.2.3 客户端客户端使用MFC编程创建基于对话框的应用程序。该程序使用Windows Socket建立同指定服务器的数据连接。当建立好HTTP链接后,可设置串口的通信参数,如:波特率,数据位,奇偶校验,停止位等。设置好串口的通信参数后就可以同服务器分配给的串口链接的外设通信了。发送数据到服务器的串口,和接收服务器发送回来的数据。3.2.4 开发工具Microsoft Visual C+ 6.0是微软公司推出的开发Win32应用程序(Windows 95/98/2000/XP/NT)的、面向对象的可视化集成工具。它的最大优点就是提供了功能强大的MFC类库,MFC是一个很大的C+类层次结构,其中封装了大量的类及其函数,很多Windows程序所共有的标准内容可以由MFC的类来提供,MFC类为这些内容提供了用户接口的标准实现方法,程序员所要做的就是通过预定义的接口把具体应用程序特有的东西填入这个轮廓,这将简化编程工作,大大的减少程序员编写的代码数量,使编程工作变得更加轻松容易。4 具体设计流程与实现4.1 安全队列数据保护是在使用多线程技术时必须要解决的关键问题,防止多个线程同时操作某一变量,导致逻辑错误,是多线程协调运行的重要内容。线程安全队列这种数据保护机可以保护共享数据,实现线程间安全的数据传输。一般地,每个进程中的线程都不知道进程中的其他线程的任何情况,除非我们在程序中明确的使他们互相可见。为了在不同时刻访问共享的资源,任何共享这些资源的线程都必须通过进程通信的手段进行调度。线程调度是一个复杂的问题,不正确的调度将导致进程的死锁。为了这种情况的发生,访问共享资源的线程必须进行同步。临界区对象只有由同一个进程的线程共享,临界区对象在某一个时刻只能由一个线程所拥有。临界区对象不保证线程对临界区的访问顺序。进程负责分配临界区所使用的内存,一般声明一个类型为CRITICAL_SECTION的变量来完成此任务。在进程的线程使用临界区之前,必须使用函数InitializeCriticalSection或InitializeCriticalSectionAndSpinCount初始化临界区。线程使用函数EnterCriticalSection或函数TryEnterCriticalSection请求对临界区的拥有权。如果临界区对象正由其他线程所拥有,则函数EnterCriticalSection无限等待该拥有权。线程使用LeaveCriticalSection释放对临界区的拥有权。进程的所有线程都可以使用函数DeleteCriticalSection释放临界区对象初始化时分配的系统资源。线程安全队列工作机制如图,操作队列的时候需要先进入临界区,操作完成后离开临界区,由此保证在任何时候都只有一个线程操作该队列。线程间的数据传输是安全可靠的。图 1 安全队列工作机制入队列相关代码:BOOL Push(const Type & item)EnterCriticalSection(&lock); /进入临界区_safe_queue_item *next=new _safe_queue_item (item);if (first=NULL) last=first=next;else last-next=next;last=next;LeaveCriticalSection(&lock); /离开临界区return TRUE;出队列相关代码:Pop() EnterCriticalSection(&lock); /进入临界区Type val;_safe_queue_item *oldFirst=first;if(first=NULL)LeaveCriticalSection(&lock); throw SB Queue underflow !; else val=first-value;first=first-next;delete oldFirst;LeaveCriticalSection(&lock); /离开临界区4.2 服务应用程序在基于NT的系统中,全部服务任务都是由服务控制管理器(SCM)系统管理。SCM维持注册表中已知服务列表,打开各项服务(即可以是开机时自动打开,也可以使用户请求打开)。SCM把服务列表和它们的打开状态保存在注册表中,新服务项在安装时加入此列表中。另外也可以删除服务项目。作为服务任务的程序是一个普通的exe文件,但是必须满足特定的要求才能确切地与SCM连接。微软已经详细编制了这些函数的程序流,必须紧密依据此流程表,否则服务项目就不能运行。要求如下:商业源代码,全套计算机免费下载 ibaidusoft更多全套设计联系QQ:1042897696最新设计大全 bylw168/sf/20XX0915/3539.1服务项目的EXE文件必须有一个普通的Main或WinMain函数,此函数必须立即(特定情况下是在30秒之内)调用函数StartServiceCrtlDispatcher。调用之后,EXE文件就在SCM中注册,并且给出一个调用函数ServiceMain(在启动服务时调用)的指针。可以更改函数ServiceMain的函数名,然后就能在ServiceMain下面的记录文本中找到所用函数名的描述。main函数应该在注册ServiceMain之后返回。不能用命令行方式运行服务的exe文件。而应该在SCM知道的服务列表中安装,SCM会调用main函数,打开EXE文件。偶然用命令行方式执行服务时一定会出错,因为它不能连接SCM。2SCM在打开服务时将调用函数ServiceMain。例如,当管理员选择“控制面板”上“服务”的start按钮时,SCM将在一个工作线程中执行函数ServiceMain。函数ServiceMain完成多项工作。其中最为主要的是立即调用函数RegisterServiceCtrlHandler,该函数能用SCM注册一个函数Handler以调用控制要求。此函数的函数名可以随便更改,但大会在Handler下面的记录文本中列出。函数RegisterServiceCtrlHandler返回一个句柄,服务在给SCM发送状态信息时将用到该句柄。函数ServiceMain还开始将完成实际服务任务的工作现程。一旦线程开始,函数ServiceMain就等待一个事件的发生。直道服务停止,函数ServiceMain才返回。之后,重新调用函数ServiceMain,SCM将重新开始该项服务。3函数Handler包含一个转换语句,用于分析来自SCM的控制请求。默认时,SCM发送以下控制常数:SERVICE_CONTROL_STOP 通知服务停止SERVICE_CONTROL_PAUSE 通知服务暂停SERVICE_CONTROL_CONTINUE 通知服务重新开始SERVICE_CONTROL_INTERROGATE 通知服务立即报告当前状态SERVICE_CONTROL_SHUTDOWN 通知服务紧急关闭用户也可以创建自定义常数(128255之间),通过SCM把它们发送到服务项。当创建一个包含上述main、ServiceMain和Handler等函数的EXE文件以及一个包含服务线程的函数时,就得到了一个完整的服务任务。图 2 服务中各部分之间的关系Main函数,这是代码的入口。是在这里解析任何命令行参数并进行服务的安装,移除,启动等。提供真正服务代码的入口函数叫 ServiceMain。在服务第一次启动的时候,将该函数的地址传递给服务管理器。处理来自服务管理器命令消息的函数。这个函数叫 Handler,服务回调函数,因为 ServiceMain 和 Handler 函数都是由系统来调用,所以它们必须遵循操作系统的参数传递规范和调用规范。也就是说,它们不能简单地作为某个 C+ 类的成员函数。这样就给封装带来一些不便,因为想把 Win32 服务的功能封装在一个 C+ 类中。为了解决这个问题,将 ServiceMain 和 Handler 函数创建成 TService 类的静态成员。这样就使得以创建可以由操作系统调用的函数。 但是,这样做还没有完全解决问题,因为系统不允许给被调用的函数传递任何形式的用户数据,所以我们无法确定对 C+ 对象特定实例的 ServiceMain 或 Handler 的调用。在这里用了一个非常简单但有局限的方法来解决这个问题。创建一个包含 C+ 对象指针的静态变量。这个变量是在该对象首次创建是进行初始化的。这样便限制每个服务应用只有一个C+对象。下面是 NTService.h 文件中的声明:class TService./ 静态数据static TService* m_pThis; / nasty hack to get object ptr.;下面是初始化 m_pThis 指针:TService:TService(const char* szServiceName)m_pThis = this;.ServiceMain函数:ServiceMain函数提供真正服务代码的入口。它完成多项工作。其中最为主要的是立即调用函数RegisterServiceCtrlHandler。之后ServiceMain做一些服务初始化的工作,为工作线程的运行提供必要的准备。最后函数ServiceMain还开始将完成实际服务任务的工作线程。一旦线程开始,函数ServiceMain就等待一个事件的发生。直到服务停止,函数ServiceMain才返回。之后重新调用函数ServiceMain,SCM将重新开始该项服务。流程如图:图 3 ServerMain函数流程初始化工作OnInit函数:OnInit函数的主要任务是初始化全局变量串口队列。扫描服务器的串口,如果串口可用,则把此串口进入安全队列。以备客户端请求使用。图 4初始化工作流程相关代码:for(i=1;i=Count;i+)sprintf(buf,.%d,i);if (.EPortAvailable=.CheckPort(buf)Queue.Push(i); /串口入队列服务工作线程ServiceThread由Run函数实现:ServiceThread由函数ServerMain打开,开始完成实际服务任务的工作线程,该线程执行服务的具体任务。该函数绑定服务器地址后监听本地端口等待客户端的连接,当客户端连接上后,创建子线程,由子线程来处理这个连接,函数继续监听本地端口。子线程处理完链接后关闭链接套接字退出。图 5 服务工作线程流程相关代码:sockaddr_in service;service.sin_family=AF_INET;service.sin_addr.s_addr=INADDR_ANY; /ip地址service.sin_port=htons(2501); /端口号bind(m_socket,(SOCKADDR*)&service,sizeof(service);listen(m_socket,20); /监听连接while (m_bIsRunning) /直到服务停止运行AcceptSocket=SOCKET_ERROR;while(AcceptSocket=SOCKET_ERROR)AcceptSocket=accept(m_socket,NULL,NULL);/接收连接/创建子线程处理该连接CreateThread(NULL,NULL,AnswerThread,(LPVOID)AcceptSocket,0,&TId);服务子线程:由类的静态成员函数作为线程函数。在线程中,首先判断服务器是否还有剩余串口可分配,也就是判断串口队列中是否为空。若为空,则提示用户服务器串口已使用完毕,请稍后在试,断开同客户端的连接。否则串口队列出队列一个串口,分配给该客户使用,接下来就是打开串口,配置串口参数,开启串口监听线程,等待客户端发送的数据。直到客户端断开连接,串口重新进入队列,等待下次的分配。服务子线程退出。图 6 服务子线程工作流程相关代码:if(!Queue.IsEmpty() /判断队列是否为空=Queue.Pop(); /出队列sprintf(buf,.%d,);/打开串口配置默认通信参数Serial.Open(buf,ClientSocket,1024,1024); Serial.StartListener(); /开启监听线程while(bytesRecv) /连接是否断开while(bytesRecv=SOCKET_ERROR)/接受客户端的数据bytesRecv=recv(ClientSocket,recvbuf,1024,0); Serial.Write(recvbuf,&Len); /写串口Serial.StopListener(); /停止监听子线程Serial.Close(); /关闭串口Queue.Push(); /串口入队列Else/发送提示信息到客户端send(ClientSocket,szBuffer,strlen(szBuffer),0); closesocket(ClientSocket);/断开连接服务的安装要使用服务,首先应进行安装。安装过程使SCM知道有这项服务存在,让SCM把它添加到服务列表中。通过调用函数OpenSCManager,打开一个到服务控制管理器的连接。然后调用函数CreateService在SCM数据库中安装服务。函数CreateService的调用中使用了打开SCM的指针,服务名,识别符以及一族填充其他值的基本参数。服务名是指在scm内部使用的服务的名字,删除服务时指定改名字可删除该服务,识别符是指在“控制面板”的“服务”中表示服务项的识别符。最后关闭服务控制管理器的连接。图 7 服务安装流程服务的卸载卸载服务时,同样需要先打开一个到服务控制管理器的连接。然后查询该服务当前是否是被停止,若还未停止,则调用函数ControlService尝试停止该服务。这样做有利于卸载服务项:如果服务在删除过程中继续运行,则“控制面板”中”服务“将保留与服务的连接,实际上服务可以继续运行;当有人试图停止该“孤儿”服务时,“服务”可能就会抗议。先停止服务再删除它,就可以避免该问题。服务停止后,调用函数DeleteService删除该服务。图 8 服务卸载流程4.3 串口通信串行口在Win 32中是作为文件来进行处理的,而不是直接对端口进行操作。在Win32环境下,可以把串口看作由文件系统访问的设备。使用标准的CreateFile()函数打开端口,再使用ReadFile()和WriteFile()函数读写数据,就如同端口只是一个文件对象一样。对于串行通信,Win 32提供了相应的文件I/O函数与通信函数,使用这些函数,可以编制出符合不同需要的通信程序。通常实现串行通信的步骤如下:1按协议的设置初始化并打开串行口,这样做就是通知Windows本应用程序需要这个串口,并封锁其他应用程序使它们不能使用此串口。2配置这个串行口。3在串口上往返地传输数据,并在传输过程中进行校验4不需要此串口时,关闭串口,即释放串口以供其它应用程序使用。在这四个步骤中,主要的程序代码集中在第3步。图 9 串口通信流程串口通信直接使用Windows API函数封装成类。应用API函数进行串口编程时,步骤如下:1.打开串口:CreateFile函数。2.建立串口通信事件:CreateEvent函数。3.初始化串口,设置串口参数:SetmState函数。4.建立

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论