网络聊天编程PPT课件

上传人:hs****ma 文档编号:593498327 上传时间:2024-09-25 格式:PPT 页数:36 大小:252.50KB
返回 下载 相关 举报
网络聊天编程PPT课件_第1页
第1页 / 共36页
网络聊天编程PPT课件_第2页
第2页 / 共36页
网络聊天编程PPT课件_第3页
第3页 / 共36页
网络聊天编程PPT课件_第4页
第4页 / 共36页
网络聊天编程PPT课件_第5页
第5页 / 共36页
点击查看更多>>
资源描述

《网络聊天编程PPT课件》由会员分享,可在线阅读,更多相关《网络聊天编程PPT课件(36页珍藏版)》请在金锄头文库上搜索。

1、第一部分第一部分 应用用实践践8.1 为应用系统加入为应用系统加入Socket支持支持8.2 编写聊天模块前的准备编写聊天模块前的准备8.3 编写聊天模块代码编写聊天模块代码第二部分第二部分 知知识点点链接接L8.1 为应用系统加入为应用系统加入Socket支持支持L8.2 编写聊天模块代码编写聊天模块代码系统功能:单击菜单中的“交谈”“对话”,弹出“对话(Socket聊天)”对话框,单击“谁在线上”可以搜索工作组中所有用户的计算机名,双击一个计算机名,该计算机名即显示在左边文本框中,单击空白文本区,单击“我要上线”可上线等待来自其他用户发送的数据并在文本框中显示,否则不能接收消息,但能够给已

2、上线的用户发送消息。图8.1 双方聊天8.1 8.1 为应用系统加入为应用系统加入SocketSocket支持支持为MFC程序加入SocketSocket支持一般有两种方法,第一种是在用MFC AppWizard(exe)创建一个单文档应用程序时,在向导的第4步选中Windows Sockets,如图所示。图8.2 Windows Sockets支持为MFC程序加入SocketSocket支持一般有两种方法,第一种是在用MFC AppWizard(exe)创建一个单文档应用程序时,在向导的第4步选中Windows Sockets,如图所示。(1)打开工程,切换到FileView,双击打开头文件

3、,在其中加入一行:#include / MFC socket extensions(2)这个库里面封装了Windows Networking(Wnet)函数,这是一组网络控制函数,比如可以利用这些函数来列举局域网内所有机器名称,IP地址以及其他相关信息。为了使用这些函数需要在中加入一行:#pragma comment(lib,mpr)(3)切换到ClassView,打开CXSCJApp下的InitInstance函数,在函数体最前面添加如下代码以初始化Sockets:BOOL CXSCJApp:InitInstance()if (!AfxSocketInit()/ 是否初始化成功AfxMess

4、ageBox(Windows通信端口初始化失败);return FALSE;(1)设置界面如图所示,新建对话框,设置标题为Sockets聊天,ID为IDD_P2PCHAT,并在菜单上添加相应的项如“对话”,并编写弹出本对话框的命令代码。 图8.3 “设置Socket聊天”对话框添加“对话”菜单项ID_P2PCHAT的COMMAND消息到CXSCJView类中,代码如下:void CXSCJView:OnP2pchat()/ TODO: Add your command handler code hereCDlgP2P myDlgP2P;myDlgP2P.DoModal();在中添加头文件:#i

5、nclude DlgP2P.h(2)设置接收文本框IDC_SHOWSTR控件的属性设置如图(左)所示,设置发送文本框IDC_SENDSTR的属性如图(右)所示。 图8.4 设置编辑框的Styles属性(3)打开列表控件的属性对话框,将“查看”选为“小图标”,利于网络聊天时各在线用户名的完全显示。单击编排(Layout)测试(Test)后显示界面如图所示。图8.5 聊天模块界面(1)为对话框新建类CDlgP2P,为控件添加关联变量如图所示。图8.6 设置控件关联变量(2)在对话框类CDlgP2P 的头文件中加入变量和函数声明。class CDlgP2P : public CDialog / Co

6、nstruction public: CDlgP2P(CWnd* pParent = NULL); / standard constructor CString GetIP(CString username); / 得到目标机器IP void GetName(char Temp64); / 取得本机名 bool connectFlag ;/ 网络连接标识 void ShowRecvData(); / 显示接收的数据 void GetLanActiveComputer(); / 获取本地活动计算机机器名称 ;(3)在文件中加入全局变量如下:static int CreatedFlag=0;/ 是

7、否已建立服务器SOCKET m_socket,m_hSocket;/ 建立套接字描述符sockaddr_in m_addr; / sockaddr_inddr_in结构为套接结构为套接字储存套接字地址信息sockaddr_in m_raddr;sockaddr_in m_caddr;char *message=NULL;/ 聊天内容接收框中的消息变量char *name=NULL;/ 聊天内容接收框中的主机名变量int nItem;/ CList控件中显示内容(主机名)的序号CString changstr;/ 中间变量CString strname;/ 同上UINT AcceptThread

8、(LPVOID lpvoid);/ 接收线程SOCKET m_cSocket; / 客户端Socket(4)取得本机名。void CDlgP2P:GetName(char Temp64) / 取本机(Local Machine)的主机名(即Windows中的本机计算机名)gethostnamegethostname(Temp,64);(5)添加WM_INITDIALOG消息,用本机用户名初始化全局变量changstr。BOOL CDlgP2P:OnInitDialog() CDialog:OnInitDialog();/ TODO: Add extra initialization herec

9、har localname64;GetName(localname);changstr=localname;return TRUE; / return TRUE unless you set the focus to a control / EXCEPTION: OCX Property Pages should return FALSE(6)在中添加GetLanActiveComputer函数,用枚举的方法找到局域网里所有打开的机器。该函数的实现代码中用到了几个枚举网络资源的函数枚举网络资源的函数,其中包括:WnetOpenEnumWnetOpenEnum函数、WnetEnumResourc

10、eWnetEnumResource函数和WnetCloseEnumWnetCloseEnum函数。(7)根据计算机名得到IP地址。CString CDlgP2P:GetIP(CString username)CString hostaddr;struct hostent *hostname=gethostbyname(username);for(int i=0;hostname!=NULL&hostname-h_addr_listi;i+)hostaddr=inet_ntoa(*(struct in_addr *)hostname-h_addr_listi);/ 得到的hostname是以网络

11、字节顺序网络字节顺序存储的,要用inet_ntoa转换得到IPIP点数点数形式形式return hostaddr;(8)创建ShowRecvData(),该函数负责将接收到的数据显示在文本接收框中。void CDlgP2P:ShowRecvData()CString tempstr;tempstr=;if(name!=NULL&message!=NULL)tempstr=name;m_showstr=message;m_showstr=tempstr+:+m_showstr; m_show.SetWindowText(m_showstr); / 显示计算机名和它发送的消息message=NUL

12、L;name=NULL;(9)编写线程AcceptThread,作用是接收来自多个客户端的连接并发送数据。该线程参数为OnCreathost()传来的对话框指针,根据该指针可以对聊天对话框中显示接收数据的IDC_SHOWSTR文本框进行操作。(10)为“我要上线”按钮添加OnCreathost()事件。编写代码时,需要用到许多SocketsSockets编程常用函数编程常用函数,包括:sockets()、bind()、listen()、connect()、accept()、send()、recv()和closesockets。主要功能是打开Socket,绑定IP和端口号,开始监听,启动线程线程

13、AcceptThread接受数据。(11)为ListCtrl控件IDC_USER添加双击事件NM_DBLCLK。void CDlgP2P:OnDblclkUser(NMHDR* pNMHDR, LRESULT* pResult) / TODO: Add your control notification handler code herePOSITION pos;m_showname.SetWindowText();nItem=0;pos=m_List.GetFirstSelectedItemPosition();/ 取第一个选择项的positonif(pos=NULL)return ;els

14、ewhile(pos)/ 如果用户选择了多项,则取最后选择的一项nItem=m_List.GetNextSelectedItem(pos); m_name=m_List.GetItemText(nItem,0);UpdateData(FALSE); / 传到“发送计算机”编辑框中,方向是变量到控件*pResult = 0;(12)为“谁在线上”按钮添加BN_CLICKED事件,该事件负责将双击事件传来的用户名加入文本框IDC_SENDNAME中。void CDlgP2P:OnFinduser() / TODO: Add your control notification handler cod

15、e hereCString strTemp;strTemp=请稍候.;m_FindBtn.SetWindowText(strTemp);m_List.DeleteAllItems(); / 先清空原来显示的计算机名列表GetLanActiveComputer(); / 再次取得局域网中的计算机名Sleep(1000); / 程序冻结1000ms,获取计算机名时避免其他操作strTemp=谁在线上?(&W);m_FindBtn.SetWindowText(strTemp);(13)为按钮IDC_SENDBUTTON添加OnSend事件,作用是根据文本框IDC_SENDNAME传入的用户名,选择服

16、务端,创建发送套接字,向指定计算机发送消息。L8.1 L8.1 为应用系统加入为应用系统加入SocketSocket支持支持L1. SocketSocket的数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket具有一个类似于文件打开的函数调用Socket,该函数返回一个整型的Socket描述符,随后建立连接,数据传输等操作都是通过该Socket实现的。Socket分为三类:流式Socket(SOCK_STREAM),数据报Socket(SOCK_DGRAM)及原始Socket(SOCK_RAW)。流式Socket为面向连接,数据报Socket为面向无连接;原始Socket主

17、要用于一些协议的开发和测试新的网络协议的实现,可以进行比较底层的操作,如IP的直接访问。Windows Sockets是微软公司的网络程序设计接口,它是从BSD UNIX Socket扩展而来的。它不仅包含了BSD UNIX Socket风格的库函数,也包含了一组对Windows的扩展库函数,使程序员能够充分利用Windows的消息驱动机制进行编程。L8.2 L8.2 编写聊天模块代码编写聊天模块代码L1. sockaddr_instruct sockaddr结构为套接字储存套接字地址信息。语法:struct sockaddr unsigned short sa_family; /* 地址家族

18、, AF_xxx */ char sa_data14; /* 14字节协议地址*/ ; 参数说明:sa_family TCP/IP协议族默认是AF_INET sa_data包含套接字中的目标地址和端口信息 为了处理struct sockaddr,使用另一个类似的结构:struct sockaddr_in(in代Internet)。struct sockaddr_in short int sin_family; /* 通信类型 */ unsigned short int sin_port; /* 端口 */ struct in_addr sin_addr; /* Internet 地址 */ u

19、nsigned char sin_zero8; /* 与sockaddr结构的长度相同*/ ; L2. gethostname函数gethostname函数用以返回本地主机的标准主机名。#include / 使用前包含头文件语法:int PASCAL FAR gethostname(char FAR *name, int namelen);参数说明:name 一个指向将要存放主机名的缓冲区指针namelen缓冲区的长度该函数把本地主机名存放入由name参数指定的缓冲区中。返回的主机名是一个以NULL结束的字符串。主机名的形式取决于Windows Sockets,它可能是一个简单的主机名,或者是

20、一个域名。然而,返回的名字必定可以在gethostbyname()和 WSAAsyncGetHostByName()中使用。如果没有错误发生,gethostname()返回0,否则它返回SOCKET_ERROR。应用程序可以通过WSAGetLastError()来得到一个特定的错误代码。错误代码:WSAEFAULT 名字长度参数太小WSANOTINTIALISED 在应用这个API前,必须成功地调用WSAStartup()WSAENTDOWN Windows Sockets实现检测到了网络子系统的错误WSAEINPROGRESS 一个阻塞的Windows Sockets操作正在进行L3. 枚举

21、网络资源的函数1 1WnetOpenEnumWnetOpenEnum函数函数WnetOpenEnum函数用于启动对网络资源进行枚举的过程。语法:DWORD WnetOpenEnum( DWORD dwScope, DWORD dwType, DWORD dwUsage,LPNETRESOURCE lpNetResource, LPHANDLE lphEnum );参数说明:DwScope表示网络枚举的范围DwType表示枚举的资源类型DwUsage表示枚举资源的用法LpNetResource用于返回网络资源信息LphEnum表示枚举的资源句柄指针2 2WnetEnumResourceWnetE

22、numResource函数函数WnetEnumResource函数用于枚举网络资源。语法:DWORD WnetEnumResource( HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize );参数说明:hEnum由WnetOpenEnum函数的参数lphEnum传入,表示枚举的资源句柄lpcCount用来决定获取的资源数目最大值lpBuffer指向枚举结果存放的缓冲区地址lpBufferSize指向枚举结果存储缓冲区大小的变量地址 3 3WnetCloseEnumWnetCloseEnum函数函数Wnet

23、CloseEnum函数用于结束一次枚举操作。语法:DWORD WnetCloseEnum( HANDLE hEnum );参数说明:hEnum由WnetOpenEnum函数的参数lphEnum传入L4. gethostbyname函数gethostbyname函数能够通过计算机的名称返回其网络信息,这个信息中包括IP地址。语法:struct hostent FAR * gethostbyname ( const char FAR * name );参数说明:name包含计算机名称的字符串L5. 网络字节顺序在Internet上传输的数据和本机内存中的数据存储顺序不同。网络字节顺序NBO(Net

24、work Byte Order):按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。主机字节顺序HBO(Host Byte Order):不同的机器HBO不相同,与CPU设计有关。计算机数据存储有两种字节优先顺序:高位字节优先和低位字节优先。Internet上数据以高位字节优先顺序(NBO)在网络上传输,所以对于在内部是以低位字节优先方式存储数据的机器,在Internet上传输数据时就需要进行转换。网络字节顺序和本机字节顺序的转换有两种类型:short(两个字节)和long(四个字节)。这个函数对于变量类型unsigned也适用。比如将short从本机字节顺序转换为网络

25、字节顺序函数:htons(),意思为“Host to Network Short”。当某数据必须按照NBO顺序,要调用函数(例如 htons())来将它从本机字节顺序(Host Byte Order)转换过来。类似的还有:htons()Host to Network Short htonl() Host to Network Long ntohs()Network to Host Short ntohl()Network to Host Long 需要说明的是,在数据结构struct sockaddr_in中,sin_addr和sin_port 需要转换为网络字节顺序,而sin_family不

26、需要。原因是sin_addr和sin_port分别封装在IP和UDP层,因此,它们必须是网络字节顺序。但是sin_family域只是被主机使用来决定在数据结构中包含什么类型的地址,所以它必须是本机字节顺序。同时sin_family没有发送到网络上,可以是本机字节顺序。 L6. IP点数形式假设已经有一个sockaddr_in结构体ina,有一个IP地址“”需要储存在其中,就要用函数inet_addr()将IP地址从点数格式转换成无符号长整型。使用方法如下: ina.sin_addr.s_addr = inet_addr(132.241.5.10); 注意,inet_addr()返回的地址已经是

27、网络字节格式,所以无须再调用函数htonl()。当inet_addr()发生错误时返回-1。上面的代码并不完整,编程时要先进行错误检查。 还可以将一个in_addr结构体输出成点数格式,要用到inet_ntoa()函数(“network to ascii”),比如:printf(%s,inet_ntoa(ina.sin_addr); 它将输出IP地址。需要注意的是inet_ntoa()将结构体in_addr作为一个参数,它返回的是一个指向一个字符的指针。它是一个由inet_ntoa()控制的静态指针,所以每次调用inet_ntoa()时,它就将覆盖上次调用时所得的IP地址。例如:char *a

28、1, *a2; a1 = inet_ntoa(ina1.sin_addr); /* 这是198.92.129.1 */ a2 = inet_ntoa(ina2.sin_addr); /* 这是132.241.5.10 */ printf(address 1: %sn,a1); printf(address 2: %sn,a2); 输出如下: address 1: 132.241.5.10 address 2: 132.241.5.10 更多信息请参考有关“网络socket编程指南”资料。L7. Sockets编程常用函数1 1创建套接字创建套接字socketsocket函数函数SOCKET s

29、ocket(int af, int type,int protocol);应用程序调用socket函数来创建一个能够进行网络通信的套接字。第一个参数指定应用程序使用的通信协议的协议族,对于TCP/IP协议族,该参数置AF_INET;第二个参数指定要创建的套接字类型,流套接字类型为SOCK_STREAM、数据报套接字类型为SOCK_ DGRAM;第三个参数指定应用程序所使用的通信协议。该函数如果调用成功就返回新创建的套接字的描述符,如果失败就返回INVALID_ SOCKET。套接字描述符是一个整数类型的值。每个进程的进程空间里都有一个套接字描述符表,该表中存放着套接字描述符和套接字数据结构的对

30、应关系。该表中有一个字段存放新创建的套接字的描述符,另一个字段存放套接字数据结构的地址,因此根据套接字描述符就可以找到其对应的套接字数据结构。每个进程在自己的进程空间里都有一个套接字描述符表,但是套接字数据结构都是在操作系统的内核缓冲里。2 2捆绑本地地址捆绑本地地址bindbind函数函数int bind( SOCKET s, const struct sockaddr FAR *name, int namelen);当创建了一个Socket以后,套接字数据结构中有一个默认的IP地址和默认的端口号。一个服务程序必须调用bind函数来给其绑定一个IP地址和一个特定的端口号。客户程序一般不必调用

31、bind函数来为其Socket绑定IP地址和端口号。该函数的第一个参数指定待绑定的Socket描述符;第二个参数指定一个sockaddr结构。该结构是这样定义的:struct sockaddr u_short sa_family; char sa_data14;其中:sa_family指定地址族,对于TCP/IP协议族的套接字,给其置AF_INET。当对TCP/IP协议族的套接字进行绑定时,通常使用另一个地址结构sockaddr_in用来存储IP地址和端口。struct sockaddr_in short int sin_family;/* Address family */ unsigned

32、 short int sin_port;/* Port number */ struct in_addr sin_addr;/* Internet address */ unsigned char sin_zero8;/* Same size as struct sockaddr */;sin_family指定协议族,在socket编程中只能是AF_INETsin_port存储端口号(使用网络字节顺序)sin_addr存储IP地址,使用in_addr这个数据结构sin_zero仅为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留3 3建立套接字的连接建立套接字的连接(

33、1)connect()函数int connect(SOCKET s,const struct sockaddr FAR *name,int namelen);客户程序调用connect函数来使客户Socket与监听于name所指定的计算机的特定端口上的服务Socket进行连接。如果连接成功,connect返回0;如果失败则返回SOCKET_ERROR。下面是一个例子:struct sockaddr_in daddr;memset(void *)&daddr,0,sizeof(daddr);daddr.sin_family=AF_INET;daddr.sin_port=htons(8888);d

34、addr.sin_addr.s_addr=inet_addr(133.197.22.4);connect(ClientSocket,(struct sockaddr *)&daddr,sizeof(daddr);(2)accept()函数SOCKET accept(SOCKET s,struct sockaddr FAR *addr,int FAR *addrlen);客户端通过一个服务端正在监听(listen())的端口连接(connect())到服务端,它的连接将加入到等待服务端接受(accept())的队列中。服务端调用accept()告诉客户端有空闲的连接。该函数将返回一个新的套接字,

35、这样就有两个套接字了,原来的一个还在侦听指定的端口,新的在准备发送(send())和接收(recv())数据。下面是一个调用accept的例子:struct sockaddr_in ServerSocketAddr;int addrlen;addrlen=sizeof(ServerSocketAddr);ServerSocket=accept(ListenSocket,(struct sockaddr *)&ServerSocketAddr,&addrlen);4 4监听连接监听连接listenlisten函数函数int listen( SOCKET s, int backlog );服务程序

36、可以调用listen函数使其流套接字s处于监听状态。处于监听状态的流套接字s将维护一个客户连接请求队列,该队列最多容纳backlog个客户连接请求。假如该函数执行成功,则返回0;如果执行失败,则返回SOCKET_ERROR。5 5数据发送数据发送send()send()函数函数int send( SOCKET s,const char FAR *buf,int len,int flags );不论是客户还是服务器应用程序都用send函数来向TCP连接的另一端发送数据。客户程序一般用send函数向服务器发送请求,而服务器则通常用send函数来向客户程序发送应答。第一个参数指定发送端套接字描述符;

37、第二个参数指明一个存放应用程序要发送数据的缓冲区;第三个参数指明实际要发送的数据的字节数;第四个参数一般置0。6 6数据接受数据接受recv()recv()函数函数int recv( SOCKET s, char FAR *buf, int len, int flags );不论是客户还是服务器应用程序都用recv函数从TCP连接的另一端接收数据。第一个参数指定接收端套接字描述符;第二个参数指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;第三个参数指明buf的长度;第四个参数一般置0。当应用程序调用recv函数时,recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发

38、送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据拷贝到buf中,recv函数返回其实际拷贝的字节数。如果recv在拷贝时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。7 7关闭套接字关闭套接字closesocketclosesocket函数函数int closesoc

39、ket(SOCKET s);closesocket函数用来关闭一个描述符为s套接字。由于每个进程中都有一个套接字描述符表,表中的每个套接字描述符都对应了一个位于操作系统缓冲区中的套接字数据结构,因此有可能有几个套接字描述符指向同一个套接字数据结构。套接字数据结构中专门有一个字段存放该结构的被引用次数,即有多少个套接字描述符指向该结构。当调用closesocket函数时,操作系统先检查套接字数据结构中的该字段的值,如果为1,就表明只有一个套接字描述符指向它,因此操作系统就先把s在套接字描述符表中对应的那条表项清除,并且释放s对应的套接字数据结构;如果该字段大于1,那么操作系统仅仅清除s在套接字描

40、述符表中的对应表项,并且把s对应的套接字数据结构的引用次数减1。closesocket函数如果执行成功就返回0,否则返回SOCKET_ERROR。L8. 线程1 1进程和线程进程和线程一个进程中的所有线程都在该进程的虚拟地址空间中,使用该进程的全局变量和系统资源。操作系统给每个线程分配不同的CPU时间片,在某一个时刻,CPU只执行一个时间片内的线程,多个时间片中的相应线程在CPU内轮流执行。由于每个时间片时间很短,所以对用户来说,仿佛各个线程在计算机中是并行处理的。操作系统是根据线程的优先级来安排CPU的时间,优先级高的线程优先运行,优先级低的线程则继续等待。线程被分为两种:用户界面线程和工作

41、者线程(又称为后台线程)。用户界面线程通常用来处理用户的输入并响应各种事件和消息。事实上,应用程序的主执行线程CWinApp对象就是一个用户界面线程,当应用程序启动时自动创建和启动,同样它的终止也意味着该程序的结束,进程终止。工作者线程用来执行程序的后台处理任务,比如计算、调度、对串口的读写操作等,它和用户界面线程的区别是它不用从CWinThread类派生来创建,对它来说最重要的是如何实现工作者线程任务的运行控制函数。2 2线程的启动线程的启动创建一个用户界面线程,首先要从CWinThread类产生一个派生类,同时必须使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREAT

42、E来声明和实现该CWinThread派生类。第二步是根据需要重载该派生类的一些成员函数,如ExitInstance、InitInstance、OnIdle、PreTranslateMessage等函数,最后启动该用户界面线程,调用其中一个版本的AfxBeginThread函数,如下面的函数原型:CWinThreadCWinThread* AfxBeginThread( CRuntimeClass AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT= THREAD_PR

43、IORITY_NORMAL, UINT nStackSize = 0, DWORD DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES= 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL = NULL );其中,pThreadClass为指向定义的用户界面线程类指针变量,nPriority为线程的优先级,nStackSize为线程所对应的堆栈大小,dwCreateFlags为线程创建时的附加标志,若为CREATE_SUSPENDED则线程启动后为挂起状态,lpSecurityAttrs为指向线程安全属性的结

44、构指针变量。对于工作者线程来说,启动一个线程,首先需要编写一个希望与应用程序的其余部分并行运行的函数。接着定义一个指向CWinThread对象的指针变量*pThread,调用另一个版本的AfxBeginThread函数,并将返回值赋给pThread。AfxBeginThread函数原型如下:CWinThreadCWinThread* AfxBeginThread( AFX_THREADPROCAfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOIDLPVOID pParam, intint nPriority = THREAD_PRIORITY_NORMAL,= THREAD_PRIORITY_NORMAL, UINTUINT nStackSize = 0, DWORD= 0, DWORD dwCreateFlags = 0= 0, LPSECURITY_ATTRIBUTESLPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL = NULL );其中,pfnThreadProc为指向工作者线程控制函数的指针,param是传送给工作者线程控制函数的任意32位值。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号