0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于Windows NT操作系统设计TCP/IP的多线程通信系统的设计

电子设计 来源:电子技术应用 作者:王金廉,谢剑英, 2020-06-08 07:49 次阅读

传统的应用程序都是单线程的,即在程序运行期间,由单个线程独占CPU的控制权,负责执行所有任务。在这种情况下,程序在执行一些比较费时的任务时,就无法及时响应用户的操作,影响了应用程序的实时性能。在监控系统,特别是远程监控系统中,应用程序往往不但要及时把监控对象的最新信息反馈给监视客户(通过图形显示),还要处理本地机与远程机之间的通信以及对控制对象的实时控制等任务,这时 ,仅仅由单个线程来完成所有任务,显然无法满足监控系统的实时性要求。在DOS系统下,这些工作可以由中断来完成。而在Windows NT下,中断机制对用户是不透明的。为此,可引进多线程机制,主线程专门负责消息的响应,使程序能够响应命令和其他事件。辅助线程可以用于完成其他比较费时的工作,如通信、图形显示和后台打印等,这样就不至于影响主线程的运行。

1、Windows NT 多线程概述

Windows NT是一个真正的抢占式多任务操作系统。在 Windows NT中,启动一个应用程序就是启动该应用程序的一个实例,即进程。进程由一个或多个线程构成,拥有内存和资源,但自己不能执行自己,而是进程中的线程被调度执行。进程至少要有一个线程,当创建一个进程时,就创建了一个线程,即主线程。主线程可以创建其他辅助线程,由主线程创建的线程又可创建线程。每个线程都可指定优先级,操作系统根据线程的优先级调度线程的执行。

Windows NT中使用多线程的方法有三种:

· 使用C多线程库函数;

· 使用CreateThread() 等Win32函数;

· 使用MFC类。

本文采用第三种方法。在Visual C++5.0 中,MFC应用程序用CWinThread 对象表示线程。基本操作如下:

· 创建新线程:调用MFC全局函数AfxBeginThread ()创建新线程。AfxBeginThread()启动新线程并返回控制,然后,新线程和调用AfxBeginThread()的线程同时运行。它的返回值为指向CWinThread对象的指针;

· 暂停/恢复线程:调用CWinThread类成员函数SuspendThread()暂停线程的运行,调用ResumeThread()成员函数恢复线程的运行;

· 终止线程:在线程内部可调用全局函数AfxBeginThread()终止线程的运行,否则,线程执行结束后,线程自动从线程函数返回并释放线程占有的资源。

2、基于TCP/IP的多线程编程

TCP/IP是lnternet上广泛使用的一种协议,可用于异种机之间的互联。TCP/IP协议本身是非常复杂的,然而在网络编程中,程序员不必考虑TCP/IP的实现细节,只需利用协议的网络编程接口Socket(亦称套接字)即可。在 Windows 中,网络编程接口是 Windows Socket它包含标准的Berkley Sockets的功能调用的集合,以及为 Windows 所做的一些扩展。TCP/IP协议的应用一般采用客户/服务器模式,面向连接的应用调用如图1所示。

基于Windows NT操作系统设计TCP/IP的多线程通信系统的设计

根据上述顺序调用函数建立连接后,通信双方便可交换数据。然而,在调用带*号的函数时,操作常会阻塞,特别是当套接字工作在同步阻塞模式(Blocking Mode)时。这时,程序无法响应任何消息。为了避免出现这种情况,本文引进辅助线程。在执行含有可能阻塞的函数的任务时,动态创建新的线程,专门处理该任务。主线程把任务交给辅助线程后,不再对辅助线程加以控制与调度。本文分别针对connect()、accept()、receive()、send()等可能阻塞的函数创建了相应的线程,如表1所示。

多线程编程常常还要考虑线程间的通信。线程间的通信可以采用全局变量、指针参数和文件映射等方式。本文采用指针参数方式。在调用AfxBeginThread()函数时,通过传递指针参数的方式在主线程与辅助线程间通信。

AfxBeginThread()函数的用法如下:

CWinThread*AfxBeginThread (AFX_THREADPROC pfnThreadproc,

LPVOID pParam

int nPriority=THREAD_PRIORITY_NORMAL,

UINT nStackSixe=0,

DWORD dwCreateFlags=0,

LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);

参数pfnThreadProc指定线程函数必须如下定义:

UINT MyControllingFunction(LPVOID pParam); 

参数pParam 是调用线程传递给线程函数pfThreadProc的参数;

其他参数一般只需采用缺省值。

指针参数通信方式就是通过参数pParam在线程间通信的,它可为指向任何数据类型的指针。本文中,定义了一个名叫EXCHANGE_INFO的结构如下:

typedef struct

{ SOCKET sServerSocket;

SOCKET *pcCoientSocket;

SOCKADDR_IN *pClientAddr;

BOOL *pbConnected;

unsigned char *pucBuffer;

int *pnMessageLen;

} EXCHANGE_INFO;

在需要通信时,先声明一个结构变量,再把变量的指针作为pParam参数,调用AfxBeginThread((AFX_THREADPROC) CSocketThread::WaitFor ConnectThread,(LPVOID)& m_Exchangeinfo)函数即可。

为了利用面向对象技术编程所具有的模块性强、便于修改、可移植性好等优点,本文还把表1中的线程封装为父类为CWinThread的自定义类CSocketThread中。还自定义了一个叫CSocketComm的新类,封装了一些函数,如CreateSocket、ConnectToServer、WaitForClient、ReadMessage、SendMessage等,这些函数屏蔽了面向连接的通信程序的实现细节,如创建、连接、发送和接收等,在这些函数里,动态创建辅助线程。

下面以CSocketComm类中的等待客户连接请求的函数WaitForClient()为例,注释说明多线程编程的具体细节。

BOOL CSocketComm::WaitForClient

{

if(m_bConnected)return( TRUE );

//配置bind函数的参数即服务器的套接字地址结构

SOCKADDR_IN Addr;

memset(&Addr,0,sizeof(SOCKADDR_IN));

Addr.sin_family=AF_INET;

ADDR.SIN_port= htonl(m_nPort); 

Addr.sin_addr.s_addrr = htonl(INADDR_ANY); 

//将套接字地址结构赋予套接字(绑定),以指定本地半相关

int nReturnValue;

nReturnValue =::bind( m_sSserverSocket,( LPSOCKADDR)&Addr,sizeof (SOCKADDR_IN )); 

if(nReturnValue == SOCKET_ERROR)  returu( FALSE );

//配置传给WaitForConnectThread线程函数的参数m_Exchangeinfo

m_Exchangeinfo.sServerSocket = m_sserverSocket;

m_Exchangeinfo.psClientSocket = &m_sClientSocket;

m_Exchangeinfo.pClientAddr = &m_ClientAddr;

m_Exchangeinfo.pbConnected = &m_bConnected;

//以m_Exchangeinfo的指针为参数调用WaitforConnectThread线程等待客户端连接

AfxBeginThread((AFX_THREADPROC)CSocketThread::

WaitForConnectThread,(LPVOID) &m_Exchanginfo); 

returi( TRUE )

}

//等待连接线程

UINT CSocketThread::WaitForConnectThread(LPVOIDpParam)

{

EXCHANGE_INFO*pExchangelnfo=(EXCHANGE_INFO*) pParam;

int nReturnValue, nClientAddrSize= Sizeof( SOCKADDR_IN);

//侦听连接

nReturnValue=:: listen(pExchangelnfo ->sServerSocket, 1); 

if( nReturnValue == SOCKET_ERROR )return(0);

//阻塞调用accept,直至有客户连接请求

 *pExchangelnfo->psClitentSocket=:: accept(pExchangelnfo->sServerSocket, (LPSOCKADDR) pEchangelnfo ->pClientAddr,&nClientAddrSize); 

if(( *pExchangelnfo->psClitentSocket)!= INVALID_SOCKET)

//通过pExchangelnfo的指针在线程间通信

 * pExchangelnfo->pbConnected TRUE;

return( 0 );

3、应用实例-高层协议的设计

在电厂和电站中,为了保证安全工作,保护系统必不可少。保护系统的电源供应通常使用两种方式。一般情况下,使用交流电系统对保护系统进行供电;当交流电系统出现故障时立即使用后备的蓄电池系统对保护系统进行供电。为了对蓄电池系统进行监控和管理,以保证蓄电池在关键时刻能正常工作,设计了在Windows NT环境下具有远程通讯功能和动态人机界面的智能蓄电池远程监控系统 。该系统由蓄电池智能管理、充电机控制、母线绝缘在线检测、声光报警、系统组态、远程通信等子系统组成,实现对蓄电池/充电机智能化远程管理和控制,对整个系统的运行状态进行实时监控,具有多媒体报警、事件处理、动态数据库、趋势画面和动态画面显示、操作提前提醒等功能。系统框图如图2所示。在远程通信模块中,远程监控机需把监控客户的操作命令及时传给本地机,本地机根据命令控制充电机,使之按照一定的方式工作,而本地机需定时向远程监控机反馈实时的充电机状态信息。它们之间的通信是基于TCP/IP的广域网通信,而且,我们引进了多线程机制以保证系统具有良好的实时性。

下面以其中的充电机控制系统为例谈谈如何使用CSocketComm类进行远程通信。为简单起见,假定本地机与远程监控机之间通信的信息仅有下面三种类型:

·本地机接收到该命令后,控制充电机按照稳压模式运行,输出电压为电压给定值;

·本地机接收到该命令后,控制充电机按照稳流定时模式运行,输出电流为电流给定值;

·本地机向远程监控机发送充电机的实时状态数据(包括输出电压、输出电流、状态指示和故障类型指示)。

在基于TCP/IP的面向连接的网络通信中,客户与服务器之间传送的是有序可靠的字节流(Byte Stream),所以程序员有必要在传输层TCP上定义自己的高层协议,设计帧结构,将字节流变成有意义的信息。在CSocketComm类中由AssembleMessage()函数把数据组合成一定的帧结构。帧结构为:

其中@为帧起始标志,#为帧终结标志

对应的结构定义如下:

typedef struct

{ int MessageType; //信息类型

int ChargerNo; //充电机编号

int DataNo; //数据类型

float Data; //数据

}MessageStruct;

需要通信时,先声明一个MessageStruct变量,根据信息内容对各成员变量赋值,传给 AssembleMessage()函数组合成帧,再调用SendMessage()函数发送给接受方。接受方接到数据后,对数据内容的解释,是由CsocketComm类中的AnalyzeMessage()函数完成的。AnalyzeMessage()函数返回一个MessageStruct变量。应用程序就可根据它的各成员变量控制充电机或动态显示充电机的状态。

总之,把多线程机制引进通信,有利于提高应用程序的实时性,充分利用系统资源。对于大型的工程应用来说,不同的线程完成不同的任务,也有利于提高程序的模块化,便于维护和扩展。本文给出了一种在Windows NT下基于TCP/IP协议的多线程通信的基本方法,根据该方法进行修改和扩充,便可设计出符合具体应用的高质量的多线程通信程序。

责任编辑:gt


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • WINDOWS
    +关注

    关注

    3

    文章

    3523

    浏览量

    88359
  • 操作系统
    +关注

    关注

    37

    文章

    6707

    浏览量

    123160
  • 线程
    +关注

    关注

    0

    文章

    504

    浏览量

    19637
收藏 人收藏

    评论

    相关推荐

    #操作系统原理 多线程模型

    操作系统多线程模型
    电子技术那些事儿
    发布于 :2022年10月17日 22:32:33

    基于TCP/IP协议和多线程通信软件的设计与实现

    ,解析后以数据表格形式显示。重点探讨了客户端/服务器模式下基于TCP/IP协议通信多线程实现过程,并利用时序图和活动图进行具体描述。讨论了在软件安装调试过程中如何解决客户端死机问题和
    发表于 05-06 09:02

    【NanoPi K1 Plus试用体验】多线程&TCP通信

    TCP通信是最常见的传输层网络通信协议,在Linux系统中非常常见,建立TCP通信的基础是传输层
    发表于 09-13 00:27

    Java操作系统支持多线程

    Windows操作系统均支持多线程进程的并发处理机制。操作系统支持多线程,使多个程序能够并发执行,以改善资源使用率和提高
    发表于 08-05 06:06

    基于TCP/IP协议的多线程通信的基本方法

    本文给出了一种在Windows NT下基于TCP/IP协议的多线程通信的基本方法,根据该方法进行
    发表于 02-04 07:08

    基于51单片机的多线程操作系统 精选资料分享

    我知道,在51单片机上运行一个操作系统,大多数情况下并不实用。但51单片机广为人知。所以我认为,用它来逐步的实现一个多线程操作系统,使得读者以更多的精力思考操作系统的设计,弱化芯片本身
    发表于 07-20 07:55

    如何利用多线程去构建一种TCP并发服务器

    TCP并发服务器,并实现客户端和服务器的传输(多个并发用户同时访问服务器)实验原理:TCP的传输模型和线程的并发执行三、主要仪器设备PC机、装有Linux操作系统的虚拟机四、...
    发表于 12-22 08:03

    Windows CE下多线程串口通信

    本文重点描述了在Windows CE5.0 内核下实现PC/104 与GPS 的通信,构建了PC/104 读写GPS 信息的硬件系统,深入剖析了Windows CE5.0 下进行
    发表于 06-04 08:37 28次下载

    利用TCP/IP实现Windows与Vxworks的通信

    结合TCP/IP 在某测控系统的实际应用,讨论了在嵌入式实时操作系统VxWorks和Windows 间实现网络
    发表于 08-05 09:27 17次下载

    多线程同步机制在应用程序与驱动程序通信中的应用

    本文对Windows NT 操作系统多线程同步机制和同步对象进行了分析,以其在检测仪和经纬仪同步通信程序开发中的应用为例,论述了如何通过共
    发表于 08-24 10:02 16次下载

    多线程在VC++串口通信程序中的应用

    本文通过一机房监控系统程序中串口通信多线程的应用来介绍Windows 9X/NT操作系统
    发表于 09-03 11:45 27次下载

    什么是Windows CE,LynxOS是什么操作系统

    什么是Windows CE   Microsoft Windows CE是从整体上为有限资源的平台设计的多线程、完整优先权、多任务的操作系统。它的模块化设计允许它
    发表于 06-17 00:36 1859次阅读

    linux多线程编程技术

    (process)中只允许有一个线程,这样多线程就意味着多进程。现在,多线程技术已经被许多操作系统所支持,包括Windows/
    发表于 10-24 16:01 5次下载

    基于Windows 操作系统内核驱动的多核CPU 线程管理

    1 引言 本文分析了Windows 系统的进程调度机制,并设计了一种基于Windows 操作系统内核驱动的多核CPU 线程管理方法,实现了一
    发表于 10-31 11:02 0次下载
    基于<b class='flag-5'>Windows</b> <b class='flag-5'>操作系统</b>内核驱动的多核CPU <b class='flag-5'>线程</b>管理

    基于Windows NT多线程实现智能蓄电池远程监控系统的设计

    Windows NT是一个真正的抢占式多任务操作系统。在 Windows NT中,启动一个应用程序就是启动该应用程序的一个实例,即进程。进程
    的头像 发表于 05-28 10:55 1810次阅读
    基于<b class='flag-5'>Windows</b> <b class='flag-5'>NT</b><b class='flag-5'>多线程</b>实现智能蓄电池远程监控<b class='flag-5'>系统</b>的设计