网络编程实用教程第7-8章-多线程编程.ppt
《网络编程实用教程第7-8章-多线程编程.ppt》由会员分享,可在线阅读,更多相关《网络编程实用教程第7-8章-多线程编程.ppt(62页珍藏版)》请在三一办公上搜索。
1、网络编程实用教程,第7章 WinSock的多线程编程,本章内容:WinSock需要多线程编程的原因:Win32操作系统下的多进程多线程机制、多线程机制在网络编程中的应用和Visual C+6.0对多线程网络编程的支持。分析了 MFC 支持的两种线程,给出了创建MFC的工作线程、创建并启动用户界面线程和终止线程的步骤。,7.1 WinSock为什么需要多线程编程,7.1.1 WinSock的两种输入输出模式,如前所述,WinSock在进行输入输出的时候,可以使用两种工作模式:“阻塞”模式:又称为同步模式“非阻塞”模式:又称为异步模式 工作在“阻塞”模式下的套接字被称为阻塞套接字,而工作在“非阻塞
2、”模式下的套接字称为非阻塞套接字。,7.1.2 两种模式的优缺点及解决方法,“阻塞”与“非阻塞”模式的优点和缺点:阻塞套接字的I/O操作工作情况比较确定,即调用、等待、返回。大部分情况下,I/O操作都能成功地完成,只是花费了等待的时间,容易编程;需要建立多个套接字连接来为多个客户服务的时候,或在数据的收发量不均匀的时候,或在输入输出的时间不确定的时候,阻塞套接字的性能低下,甚至无能为力。,使用非阻塞套接字,需要编写更多的代码,因为必须恰当地把握调用I/O函数的时机,尽量减少无功而返的调用,还必须详加分析每个Winsock调用中收到的错误,采取相应的对策,这种I/O操作的随机性使得非阻塞套接字显
3、得难于操作。所以必须采取适当的对策,让阻塞和非阻塞套接字能够满足各种场合的要求。对于非阻塞工作模式:引入了五种“套接字I/O模型”。阻塞的工作模式,则引入了多线程机制。,7.2 Win32操作系统下的多进程多线程机制,7.2.2 Win32 OS支持多线程,应用程序、进程及线程的关系 DOS是单用户单任务的。Win32操作系统是多任务的,并且支持一个进程中有多个线程。一个线程(thread)是进程内的一条执行路径,是一个应用程序中的一条可执行路径。一个进程中至少要有一个线程,称为主线程。当启动了一个应用程序时,操作系统将为它创建了一个进程,同时创建该进程的主线程,并开始执行主线程。主线程可以创
4、建并启动其他辅助线程,由主线程创建的线程又可以创建并启动更多的线程。,7.2.2 Win32 OS支持多线程,单CPU分时地运行进程中的各个线程,7.2.3 多线程机制在网络编程中的应用,如果一个应用程序,有多个任务需要同时进行处理,则适合使用多线程机制。对于网络上客户机软件:采用多线程,能克服在单线程的编程模式下,由于阻塞等待而产生的客户程序就不能及时响应用户的操作命令的问题。对于网络上服务器软件:采用多线程的编程技术,能更好地为多个客户服务。对于一个客户:采用多线程机制也能大大提高应用程序的运行效率。网络在线实时监控软件:,7.3 VC6.0对多线程网络编程的支持,VC6.0环境下,两种开
5、发程序的方法:直接使用Win32 API来编写Win32 应用程序利用MFC 基础类库编写 C+风格的应用程序。在这两种Windows应用程序的开发方式下,多线程的编程原理是一致的。,7.3.1 MFC支持的两种线程,微软的基础类库MFC提供了对于多线程应用程序的支持。在MFC中,线程分为两种:用户接口线程:(user-interface thread),或称用户界面线程;工作线程:(the worker thread),这两类线程可以满足不同任务的处理需求。,1、用户接口线程 作用:用于处理用户的输入,响应用户产生的消息。MFC为用户接口线程提供了一个消息泵。同时包含一个消息循环,以应对各种
6、事件。MFC应用程序的CWinApp类对象是一个典型的用户接口线程 在MFC应用程序中,CWinThread是用户接口线程的基类,CWinApp就是从CWinThread 类派生出来的,编写用户接口线程候,也需要从CWinThread 类派生。,2工作线程 工作线程(worker thread),适用于处理那些不要求用户输入并且比较消耗时间的其他任务。对用户来说,工作线程运行在后台。这就使得工作线程特别适合去等待一个事件的发生。CWinThread 类同样是工作线程的基类。在编写工作线程的时候,可以调用MFC的AfxBeginThread函数,来创建CWinThread对象。,7.3.2 创建
7、MFC的工作线程,利用MFC创建工作线程的步骤:第一步:编程实现控制函数第二步:创建并启动工作线程 一般不必从CWinThread派生一个类。如果需要一个特定版本的 CWinThread 类,也可以去派生;但对于大多数的工作线程是不要求的。可以不作任何修改地使用CWinThread类。,7.3.2 创建MFC的工作线程,1、编程实现控制函数 一个工作线程对应一个控制函数。线程执行的任务都应编写在控制函数之中,规定了该线程的执行代码,当控制函数执行结束而退出时,线程也就随之终止。编写工作线程的控制函数必须遵守一定的格式,控制函数的原型声明是:UINT ControlFunctionName(LP
8、VOID pParam);pParam是一个数据结构;,7.3.2 创建MFC的工作线程,2创建并启动工作线程(Starting the thread)启动线程:即开始运行它对应的控制函数。在主线程或其他线程中调用AfxBeginThread()函数就可以创建新的线程,并使新线程开始运行。一般将线程的创建者称为新线程的父线程。AfxBeginThread()函数有两个重载的版本,区别在于使用的入口参数不同。,7.3.2 创建MFC的工作线程,CWinThread*AfxBeginThread(AFX_THREADPROC pfnThreadProc,/控制函数的地址 LPVOID pParam
9、,/数据结构的指针,传数据给线程控制函数 int pPriority=THREAD_PRIORITY_NORMAL,/优先级 UINT nStackSize=0,/线程的堆栈大小(缓冲区)DWORD dwCreateFlags=0,/线程的运行状态,是否被挂起 LPSECURITY_ATTTRIBUTES lpSecurityAttrs=NULL/安全属性);后面4个参数为可选参数。,创建工作线程的例子,3、创建工作线程的例子功能:求长度为N的数组Arry的各元素的和。编程实现线程控制函数(1)/首先定义了一个结构:struct int N;/数组元素的个数。double*Arry;/指向一个
10、双精度实数的数组myData;/定义了此结构类型的变量,省略了初始化的代码myData ss;,创建工作线程的例子,(2)/接着定义线程的控制函数。UINT MyCalcFunc(LPVOID pParam)/如果入口参数为空指针,终止线程。if(pPara=NULL)AfxEndThread(MY_NULL_POINTER_ERROR);int N=pPara-N;/数组的元素个数。double*Arry=pPara-Arry;/指向数组的第一个元素。double sum=0;/数组元素之和。for(int i=0;iN;i+)sum+=Arryi;/求和。CString bb;bb.For
11、mat(“数组的和是:%d”,sum);/格式化显示字符串。AfxMessageBox(bb);/显示结果。return 0;,改为:pPara,创建工作线程的例子,调用AfxBeginThread()来创建并启动这个线程。将控制函数名和结构变量的地址作为参数传递,其他的参数省略,使用默认值。AfxBeginThread(MyCalcFunc,一旦调用了此函数,线程就被创建,并开始执行线程函数。当数据的计算完成时,函数将停止运行,相应的线程也随即终止。线程拥有的堆栈和其他资源都将释放。CWinThread对象将被删除。,创建工作线程的例子,4创建工作线程的一般模式可以得出创建工作线程的一般模式
12、:定义一个结构myData用于传递数据;工作线程控制函数的框架;UINT MyThreadProc(LPVOID pPara)if(pPara=NULL)AfxEndThread(MY_NULL_POINTER_ERROR);return 1;,创建工作线程的例子,/利用入口参数作某些工作。return 0;/线程成功地完成并返回。在程序的另一个函数中插入以下代码。.myData ss;AfxBeginThread(MyThreadProc,ss);,7.3.3 创建并启动用户界面线程,用户界面线程允许用户使用更多的用户界面对象,如对话框或其他窗口。因此,要使用用户界面线程,需要做更多的工作:
13、创建并启动用户界面线程要经过三个步骤:从CWinThread类派生出自己的线程类;改造这个线程类,使它能够完成用户希望的工作创建并启动用户界面线程。,7.3.3 创建并启动用户界面线程,1、从CWinThread类派生出自己的线程类 要创建一个用户界面线程,首先从CWinThread 类派生出自己的线程类,可借助ClassWizard来完成。2、改造自己的线程类 对这个派生的线程类作以下改造工作:在类的.h头文件中,用DECLARE_DYNCREATE宏来声明这个类(使其支持动态创建);DECLARE_DYNCREATE(class_name),7.3.3 创建并启动用户界面线程,在类的.CP
14、P文件中,用IMPLEMENT_DYNCREATE宏来实现这个类。调用格式是:IMPLEMENT_DYNCREATE(class_name,base_class_name)两个参数分别是参数是线程类名和它的基类名。,7.3.3 创建并启动用户界面线程,对派生类的改造:这个线程类须重载它的基类的某些成员函数,如该类的InitInstance()成员函数;对于其他成员函数,可以有选择地重载。创建新的用户界面窗口类,并建立线程类与用户界面窗口类的联系。利用类向导为新建的线程类添加控件成员变量,添加响应消息的成员函数,编写实现代码。,7.3.3 创建并启动用户界面线程,WinThread的成员函数包括
15、:,7.3.3 创建并启动用户界面线程,3创建并启动用户界面线程 可以使用MFC提供的AfxBeginThread()函数的另一个创建并启动用户界面线程,调用格式是:CWinThread*AfxBeginThread(CRuntimeClass*pThreadClass,/继承的线程类指针 int pPriority=THREAD_PRIORITY_NORMAL,/优先级 UINT nStackSize=0,/创建线程的堆栈大小 DWORD dwCreateFlags=0,/线程的状态 LPSECURITY_ATTTRIBUTES lpSecurityAttrs=NULL);,7.3.3 创建
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 网络 编程 实用教程 多线程
链接地址:https://www.31ppt.com/p-6016917.html