第三章 MFC Winsock类编程
网络编程CAsyncSocket类

• Connect()成员函数的两种格式:
BOOL Connect( LPCTSTR lpszHostAddress, UINT nHostPort ); – lpszHostAddress指定服务器地址的字符串,可以使用域名 ()或IP地址(128.56.22.8); – lpSockAddrLen给出lpSockAddr结构变量中地址的长度, 以字节为单位。 BOOL Connect( const SOCKADDR* lpSockAddr, int nSockAddrLen );
二、CAsyncSocket类接受处理的消息事件(3)
(4) FD_CONNECT事件通知:通知请求连接的套接字,连接
的要求已被处理。
• 当客户端的连接请求已经被处理时产生该事件。 • 该事件仅对流式套接口有效,发生在客户端。 • 有两种情况: – 服务器已经接收了连接请求,双方的连接已经建立,通 知客户端套接口,可以用来传输数据了; – 连接情况被拒绝,通知客户套接口,它所请求的连接失 败。
– (2)CSocket类更容易使用。CSocket管理了通信的许多方面,如 字节顺序问题和字符串转换问题。这些在使用原始API或 CAsyncSocket类时,都必须用户自己做。 – (3)CSocket类为Windows消息的后台处理提供了阻塞的工作模 式,这是CArchive同步操作所必须的。
MFC的两种编程模式- CSocket类
• CSocket类从CAsyncSocket类派生,是对Windows Sockets API的高级封装。 • CSocket类继承了CAsyncSocket类的许多成员函数,用法 一致。 • CSocket类的高级表现在三个方面:
– (1)CSocket结合archive类来使用套接字。
MFC实现简单网络聊天程序

MFC实现简单网络聊天程序MFC(Microsoft Foundation Classes)是微软公司提供的一个应用程序框架,用于开发Windows系统上的图形用户界面程序。
在此基础上,我们可以利用MFC来实现简单的网络聊天程序。
首先,我们需要创建一个MFC应用程序项目。
使用Visual Studio打开,选择MFC应用程序向导,选择对话框风格。
然后,设置对话框的布局,包括聊天消息显示框、消息输入框、发送按钮等控件。
接下来,我们需要使用Socket编程来实现网络通信功能。
MFC提供了CSocket类,我们可以使用它来处理数据的发送和接收。
在对话框类中添加成员变量m_socket,类型为CSocket。
在OnInitDialog函数中,我们需要创建Socket,并进行连接。
可以通过使用Create函数创建CSocket对象,并调用Connect函数来连接指定的地址和端口号。
例如,可以连接到本地主机上的一些端口,这样就可以进行本地测试。
然后,我们需要添加事件处理函数来处理发送和接收消息。
当发送按钮被点击时,可以通过调用Socket对象的Send函数将消息发送给服务器。
可以使用CString类来处理字符串数据。
当接收到消息时,可以通过调用Socket对象的Receive函数将消息接收到的缓冲区中。
为了提供实时地聊天消息显示功能,我们需要使用SetWindowText函数将数据显示到聊天消息显示框中。
当接收到消息时,可以将消息显示在聊天消息显示框中,同时可以使用UpdateData函数实时更新界面。
在程序结束时,我们需要断开连接并销毁Socket对象。
在析构函数中,可以调用Shutdown函数来关闭连接,然后销毁Socket对象。
除了基本的发送和接收消息功能,我们还可以添加一些其他的功能,比如可以使用菜单栏来选择连接和断开服务器,可以添加登录和注册功能等。
这些可以根据实际需求进行扩展。
总结起来,通过使用MFC应用程序框架和Socket编程,我们可以实现简单的网络聊天程序。
第3章 WinSock编程初步-Windows网络编程基础教程(第2版)-杨传栋-清华大学出版社

注意:
➢ 熟练掌握常用WinSock API函数的功能和使用方法是利用 Windows Socket进行网络编程的基础。
➢ 要掌握WinSock API函数,首先要记住该函数的名称与函 数的主要功能,其次要清楚各参数的类型及作用,以及函 数返回值的类型及意义,最后还要掌握函数成功执行的必 要条件,了解造成函数不能成功执行的常见原因。
➢ 不仅包括了Berkeley Sockets风格的库函数,同时也提供了 一套Windows所特有的扩展库函数,使程序员能够使用 Windows系统的消息驱动机制。
➢ 应用程序调用WinSock的API函数实现相互之间的通信,而 WinSock API函数又利用下层Windows操作系统中的网络 通信协议和相关的系统调用实现其通信功能。
1.包含WinSock头文件:在程序文件首部使用编译预处理命 令“#include”,将WinSock头文件包含进来。例如:
#include <WinSock2.h> 2.链接WinSock导入库,有两种方式:
✓ 通过在项目属性页中的“配置属性\链接器\输入”的 “附加依赖项”中直接添加导入库名字
✓ 在程序中使用预处理命令“#pragma comment”。例 如,程序要使用WinSock2时,可使用如下预处理命令: #pragma comment (lib, "Ws2_32.lib")
➢ 由于WinSock2完全兼容WinSock1,因此,当系统中安装 的是WinSock2时,程序中即可以使用WinSock1的头文件 和导入库也可以使用WinSock2的头文件和导入库,但如果 要使用只有WinSock2才有的功能,那就只能使用 WinSock2的头文件和导入库。
MFC编程基础

9
2 最简单的MFC应用程序
学习MFC程序的组织方式,生成一个工程。 创建工程要点
Win32 Project Empty project 在共享 DLL 中使用 MFC
10
2 最简单的MFC应用程序
学习MFC程序的组织方式,生成一个工程。 创建工程要点
Win32 Project,Empty project,在共享 DLL 中使用 MFC
2 最简单的MFC应用程序
2 最简单的MFC应用程序
13
2 最简单的MFC应用程序
WinMain()函数,由MFC库后台自动提供; CWinApp类:
对基于MFC的程序重要,其对象包括启动、初始化、运行 和关闭应用程序所需的一切代码。 需要由CWinApp派生出工程自己的应用程序类 虚函数InitInstance(),需要重写,包含创建和显示应用程序 窗口的代码,由WinMain()函数调用; 该类继承的其它成员不变。
2014-5-17
26
消息映射例 class CSketcherApp : public CWinAppEx { public: 为了使用消息映射宏,还需要在类声明 的结尾用DECLARE_MESSAGE_MAP宏, CSketcherApp(); 该宏对类实现源文件中所定义的消息映 // 重写 射进行初始化。 public: virtual BOOL InitInstance(); virtual int ExitInstance(); // 实现 UINT m_nAppLook; virtual void PreLoadState(); 用于区分消息处 virtual void LoadCustomState(); 理函数和类中 virtual void SaveCustomState();
MFC下CSocket编程详解

MFC下CSocket编程详解:1. 常用的函数和注意事项(详细的函数接口说明请查看MSDN):CSocket::Create 初始化(一般写服务器程序都不要用为好,用下面的CSocket::Socket 初始化)CSocket::Socket初始化CSocket::SetSockOpt 设置socket选项CSocket::Bind 绑定地址端口CSocket::Connect 连接CSocket::Listen 监听CSocket::Accept 接收外部连接的socketCSocket::Send 发送内容CSocket::Receive 接收内容CSocket::Close 关闭(不等于delete)1) 在使用MFC编写socket程序时,必须要包含<afxsock.h>头文件。
2) AfxSocketInit() 这个函数,在使用CSocket前一定要先调用该函数,否则使用CSocket会出错;并且该函数还有一个重要的使用方式,就是在某个线程下使用CSocket 前一定要调用,就算主线程调用了该函数,在子线程下使用CSocket 也要先调用该函数,要不会出错。
3) 还要注意的是, Create 方法已经包含了Bind 方法,如果是以Create 方法初始化的前提下不能再调用Bind ,要不一定出错。
2. 以下是使用例子代码,通过例子来学习如何使用CSocket 进行编程,1) 客户端主要代码://初始化AfxSocketInit();//创建CSocket 对象CSocket aSocket;CString strIP;CString strPort;CString strText;this->GetDlgItem(IDC_EDIT_IP)->GetWindowText(strIP);this->GetDlgItem(IDC_EDIT_PORT)->GetWindowText(strPort);this->GetDlgItem(IDC_EDIT_TEXT)->GetWindowText(strText);//初始化CSocket 对象, 因为客户端不需要绑定任何端口和地址, 所以用默认参数即可if(!aSocket.Create())...{char szMsg[1024] = ...{0};sprintf(szMsg, "create faild: %d", aSocket.GetLastError());AfxMessageBox(szMsg);return;}//转换需要连接的端口内容类型int nPort = atoi(strPort);//连接指定的地址和端口if(aSocket.Connect(strIP, nPort))...{char szRecValue[1024] = ...{0};//发送内容给服务器aSocket.Send(strText, strText.GetLength());//接收服务器发送回来的内容(该方法会阻塞, 在此等待有内容接收到才继续向下执行)aSocket.Receive((void *)szRecValue, 1024);AfxMessageBox(szRecValue);}else...{char szMsg[1024] = ...{0};sprintf(szMsg, "create faild: %d", aSocket.GetLastError());AfxMessageBox(szMsg);}//关闭aSocket.Close();2)服务器端代码:unsigned int StartServer(LPVOID lParam)...{//初始化Winscokif (!AfxSocketInit())...{AfxMessageBox(IDP_SOCKETS_INIT_FAILED);return 1;}m_exit = false;CServerDlg *aDlg = (CServerDlg *)lParam;CString strPort;aDlg->GetDlgItemText(IDC_EDIT_PORT, strPort);UINT nPort = atoi(strPort);//socket------------------------------------------------CSocket aSocket, serverSocket;//最好不要使用aSocket.Create创建,因为容易会出现10048错误if (!aSocket.Socket())...{char szError[256] = ...{0};sprintf(szError, "Create Faild: %d", GetLastError());AfxMessageBox(szError);return 1;}BOOL bOptVal = TRUE;int bOptLen = sizeof(BOOL);//设置Socket的选项, 解决10048错误必须的步骤aSocket.SetSockOpt(SO_REUSEADDR, (void *)&bOptVal, bOptLen, SOL_SOCKET); //监听if(!aSocket.Listen(10))...{char szError[256] = ...{0};sprintf(szError, "Listen Faild: %d", GetLastError());AfxMessageBox(szError);return 1;}CString strText;aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);strText += "Server Start! ";aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);while(!m_exit)...{//接收外部连接if(!aSocket.Accept(serverSocket))...{continue;}else...{char szRecvMsg[256] = ...{0};char szOutMsg[256] = ...{0};//接收客户端内容:阻塞serverSocket.Receive(szRecvMsg, 256);sprintf(szOutMsg, "Receive Msg: %s ", szRecvMsg);aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);strText += szOutMsg;aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);//发送内容给客户端serverSocket.Send("Have Receive The Msg", 50);//关闭serverSocket.Close();}}//关闭aSocket.Close();serverSocket.Close();aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);strText += "Have Close!";aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);return 0;}//绑定端口if (!aSocket.Bind(nPort))...{char szError[256] = ...{0};sprintf(szError, "Bind Faild: %d", GetLastError());AfxMessageBox(szError);return 1;}3) SDK 下的服务器端代码//子线程函数unsigned int StartServer(LPVOID lParam)...{//初始化Winsock, AfxSocketInit() 也是封装了这些语句, 不过AfxSocketInit() 所做的事比这里多些WSADATA wsaData;//Winsock 的版本, 建议用1.1 ,兼容性好WORD wVersionRequested = MAKEWORD(1, 1);int nResult = WSAStartup(wVersionRequested, &wsaData);if (nResult != 0)...{return 1;}//-----------------------------------------------------m_exit = false;CServerDlg *aDlg = (CServerDlg *)lParam;CString strPort;aDlg->GetDlgItemText(IDC_EDIT_PORT, strPort);UINT nPort = atoi(strPort);//socket------------------------------------------------//接口对象SOCKET aSocket, serverSocket;//寻址相关结构sockaddr_in serverSockaddr;memset(&serverSockaddr, 0, sizeof(serverSockaddr));aSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (aSocket == INV ALID_SOCKET)...{char szError[256] = ...{0};sprintf(szError, "Create Faild: %d", GetLastError());AfxMessageBox(szError);return 1;}//注意,该处非常重要,取值的正确与否决定关闭scoket后端口是否能正常释放BOOL bOptVal = TRUE;int bOptLen = sizeof(BOOL);//设置socket 选项, SOL_SOCKET 和SO_REUSEADDR 一起使用, 并且后面的参数如上,关闭scoket后端口便能正常释放setsockopt(aSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&bOptVal, bOptLen);//寻址相关结构sockaddr_in aSockaddr;memset(&aSockaddr,0,sizeof(aSockaddr));aSockaddr.sin_family = AF_INET;aSockaddr.sin_addr.s_addr = htonl(INADDR_ANY);aSockaddr.sin_port = htons((u_short)nPort);//绑定: 注意参数的类型转换if(bind(aSocket,(sockaddr *)&aSockaddr, sizeof(aSockaddr)) == SOCKET_ERROR)...{char szError[256] = ...{0};sprintf(szError, "Bind Faild: %d", GetLastError());AfxMessageBox(szError);return 1;}//监听if(listen(aSocket, 10) == SOCKET_ERROR)...{char szError[256] = ...{0};sprintf(szError, "Listen Faild: %d", GetLastError());AfxMessageBox(szError);return 1;}CString strText;aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);strText += "Server Start! ";aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);while(!m_exit)...{//接收外部连接, 非阻塞serverSocket = accept(aSocket, (sockaddr *)&serverSockaddr, 0);if(serverSocket == INV ALID_SOCKET)...{continue;}elsechar szRecvMsg[256] = ...{0};char szOutMsg[256] = ...{0};//接收客户端内容: 阻塞recv(serverSocket, szRecvMsg, 256, 0);sprintf(szOutMsg, "Receive Msg: %s ", szRecvMsg);aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);strText += szOutMsg;aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);//发送内容给客户端send(serverSocket, "Have Receive The Msg", 50, 0);//关闭closesocket(serverSocket);}}//关闭closesocket(aSocket);closesocket(serverSocket);aDlg->GetDlgItemText(IDC_EDIT_LOG, strText);strText += "Have Close!";aDlg->SetDlgItemText(IDC_EDIT_LOG, strText);//当你使用完Winsock接口后,要调用下面的函数对其占用的资源进行释放WSACleanup();return 0;}3. 总结1) MFC进行编程的确比较简单, 用的代码比较少, 又容易管理。
MFC_Socket_编程教程

MFC Socket 编程(一)实验指导(ps:这是一个傻瓜教程,制作人没学过什么C,C++等,原理基本完全不了解,本教程的目的只为广大像我一样没有基础的同学,完成本次试验的参考性最基本的参考,如有不妥,见笑!)实验目的:1、了解熟悉MFC及Socket编程的基本原理和方法。
2、通过自己编程实现简单的流套接字的C/S模型。
实验内容:1、通过MFC编程,实现信息输入窗口,包括姓名、学号、课程名和课程号;有“提交”和“重置”按钮。
“提交”按钮实现将输入信息以弹出对话框形式显示;“重置”按钮实现将输入信息清空。
2、采用Socket编程,实现简单的C/S模型(客户端与服务器端通信过程);编写服务器端,使之运行;将1作为客户端,点击“提交”按钮,将1中信息发送的服务器端。
实验原理:实验步骤:(给出一最简单的例子,参考完成)客户端:(1)打开VC6.0,新建工程(图一)(2)Projects——>MFC AppWizard[exe]——>Project name(给客户端取个工程名)——>OK(图二)(3)选Dialog based——>Next(图三)(4)注意勾选Windows Sockets——>Next——>Finsh(图四)(5)现在就可以看到如下界面了,MFC最基本界面,自己点点右面的工具条,基本功能都能懂了。
我们本次就用及三个按钮。
(图五)(6)运用那三个按钮先编出,我们需要的基本界面如下(这是个最简单的,应适当扩展)。
(图六)(7)在界面上点右键,ClassWizard,看到如下界面,在Member Variables中给成员变量命名,我们对输入框的内容命名为m_name.(图七)(8)现在编译下,运行就能看到我们编好的对话框,可以输入内容,但是现在没有任何功能(图八)(9)我们现在来添加功能,把运行的这个窗口关闭,回到我们的编辑页面,我们以提交按钮为例,双击提交按钮弹出(图九)Member function name 可改可不改,直接点击OK,然后会自动弹到按钮功能编辑的地方(图十)我们就在此添加按钮的功能,在此添加UpdateData(TRUE); //更新控件值, 参数为FALSE时,用控件值更新窗口显示MessageBox(m_name);//弹出消息对话框关于重置按钮的功能如法炮制,不在啰嗦。
MFC使用教程

MFC使用教程第一部分:MFC简介Visual C++ 不仅仅是一个编译器。
它是一个全面的应用程序开发环境,使用它你充分利用具有面向对象特性的C++ 来开发出专业级的Windows 应用程序。
为了能充分利用这些特性,你必须理解C++ 程序设计语言。
掌握了C++,你就必须掌握Microsoft 基本类库(MFC) 的层次结构。
该层次结构包容了Windows API 中的用户界面部分,并使你能够很容易地以面向对象的方式建立Windows 应用程序。
这种层次结构适用于所有版本的Windows 并彼此兼容。
你用MFC 所建立的代码是完全可移植的。
简单介绍MFC的基本概念和术语以及事件驱动程序设计方法。
输入、编译和运行一个简单的MFC程序。
第二部分中将详细解释这些代码。
第三部分讨论了MFC控件和如何定制它们。
什么是MFC?如果你要建立一个Windows 应用程序,应该如何下手?好的开端是从设计用户界面开始。
首先,你要决定什么样的用户能使用该程序并根据需要来设置相应的用户界面对象。
Windows 用户界面有一些标准的控件,如按钮、菜单、滚动条和列表等,这对那些Windows 用户已经是很熟悉了。
要记住的是,作为程序员必须选择一组控件并决定如何把它们安排到屏幕上。
传统上,你需要在纸上做一下用户界面的草图,直到对各元素感到满意为止。
这对于一些比较小的项目,以及一些大项目的早期原型阶段是可以的。
下一步,是要实现代码。
为任何Windows 平台建立应用程序时,程序员都有两种选择:C 或C++。
使用C,程序员是在Windows 应用程序界面( API ) 的水平上编写代码。
该界面是由几百个 C 函数所组成,这些函数在Windows API 参考手册中都有介绍。
对于Windows NT, API 被称为"Win32 API",以区别于其用于Windows 3.1的16位API, Microsoft 也提供了C++ 库,它位于任何Windows API 之上,能够使程序员的工作更容易。
MFC编程

MFC编程微软基础类库(MFC:Microsoft Foundation Class)是微软为Windows程序员提供的一个面向对象的Windows 编程接口,它大大简化了Windows编程工作。
使用MFC类库的好处是:首先,MFC提供了一个标准化的结构,这样开发人员不必从头设计创建和管理一个标准Windows应用程序所需的程序,而是“站在巨人肩膀上”,从一个比较高的起点编程,故节省了大量的时间;其次,它提供了大量的代码,指导用户编程时实现某些技术和功能。
MFC库充分利用了Microsoft开发人员多年开发Windows程序的经验,并可以将这些经验融入到你自己开发的应用程序中去。
对用户来说,用MFC开发的最终应用程序具有标准的、熟悉的Windows界面,这样的应用程序易学易用;另外,新的应用程序还能立即支持所有标准Windows特性,而且是用普通的、明确定义的形式。
事实上,也就是在Windows应用程序界面基础上定义了一种新的标准——MFC标准。
为了更好的理解MFC,我们有必要了解一下MFC的历史。
2.4.1 MFC历史开始,Microsoft建立了一个AFX小组,AFX代表Application Framework,即应用程序框架。
据说创建该小组原意是为了发布一个Borland C++的OWL的竞争性产品,因为那时侯Borland 公司的应用程序框架OWL(object Windows Language)已经做的相当成功。
AFX小组象OWL那样,提出了一个高度抽象Windows API的一个类库。
他们采用自顶向下的设计方法,逐步将对象抽象出来,并施加到Windows上。
然后,他们试着花了几个月时间用这个类库来编写应用程序,结果发现这个类库偏离Windows API实在太远,过分抽象并没有太大的实用性,相反大大降低了应用程序的效率。
于是,他们干脆放弃了整个AFX类库,对类库进行重新设计。
这次,他们采用了自底向上的方法,从已有的Windows API着手,将类建立在Windows API对象基础上,设计出后来成为MFC1.0的一个类库。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3.1 MFC简介
2. MFC对象和Windows对象的关系
应用的数据结构不同
MFC对象是相应C++类的实例,由MFC或者编程者定义 Windows对象是Windows操作系统内部结构的实例,通 过句柄来引用
所处的层次不同
MFC对象是高层的 Windows对象是低层的
创建的机制不同
3.2 CAsyncSocket类
使用CAsyncSocket类编程的一般步骤
序号 服务器(Server) 客户机(Client)
1
2
//构造一个套接字 CAsyncSocket sockSrvr;
//创建SOCKET句柄,绑定到指定的端 口 sockSrvr.Create(nPort);
//构造一个套接字 CAsyncSocket sockClient;
1.六种套接字相关的事件与通知消息
参数Ievent可以选用的六个符号常量是在winsock.h 文件中定义的。 #define FD_READ #define FD_WRITE #define FD_OOB #define FD_ACCEPT 0x01 0x02 0x04 0x08
#define FD_CONNECT
3.1 MFC简介
3. 消息映射的实现
Windows应用程序的输入由Windows系统以消 息的形式发送给应用程序的窗口。这些窗口通 过窗口过程来接收和处理消息,然后把控制返 还给Windows ① 消息的分类:
队列消息和非队列消息 系处理 消息结构:
举例:创建一个使用27端口的流式异步套接 字对象。
CAsyncSocket* pSocket = new CAsyncSocket;
int nPort = 27;
pSocket->Create( nPort, SOCK_STREAM );
3.2.3 关于CAsyncSocket类可以接受并处理的 消息事件
//创建SOCKET句柄,使用默认参数 sockClient.Create();
3
4 5
//启动监听,时刻准备接受连接请求 sockSrvr.Listen();
//请求连接到服务器 sockClient.Connect(strAddr.nport); //构造一个新的空的套接字来接受连接 CAsyncSocket sockRecv; sockSrvr.Accept(sockRecv); //接收数据 sockRecv.Receive(pBuf, nLen); //发送数据 sockRecv.Send(pBuf, nLen); //关闭套接字对象 sockRecv.Close(); //发送数据 sockClient.Send(pBuf, nLen); //接收数据 sockClient.Receive(pBuf, nLen); //关闭套接字对象 sockClient.Close();
virtual void OnClose(int nErrorCode); FD_CLOSE事件
对应
virtual void OnOutOfBandData(int nErrorCode); 对 应 FD_OOB事件
当某个网络事件发生时,MFC框架会自动 调用套接字对象的对应的事件处理函数。这 就相当给了套接字对象一个通知,告诉它某 个重要的事件已经发生。所以也称之为套接 字类的通知函数(notification functions) 或回调函数(callback functions)。
格 式 一 : BOOL Connect( lpszHostAddress, UINT nHostPort ); LPCTSTR
格 式 二 : BOOL lpSockAddr,
Connect( const
SOCKADDR*
int nSockAddrLen );
如 果 调 用 成 功 或 者 发 生 了 WSAEWOULDBLOCK错误,当调用结束返回 时,都会发生FD_CONNECT事件,MFC框架 会自动调用客户端套接字的OnConnect()事 件处理函数,并将错误代码作为参数传送给它。 它的原型调用格式如下,
MFC消息映射的实现方法
MFC使用ClassWizard帮助实现消息映射,它在源码中添加一 些消息映射的内容,并声明和实现消息处理函数。
3.1 MFC简介
4. MFC应用程序的执行过程
MFC程序的启动
第一、AFX内部初始化,包括应用程序对象状态初始 化和主线程初始化 第二、执行由MFC框架提供的标准函数WinMain() 第三、调用CWinApp类的虚函数InitInstance(),初始化 应用程序的当前实例 第四、调用CWinApp的Run()函数,运行消息循环和 空闲处理 第五、当收到WM_QUIT消息,调用ExitInstance()函 数,退出消息循环,并做应用程序退出时的清理工作
第三章 MFC Winsock类编程
2011-03-31
主要内容
3.1 MFC简介 3.2 CAsyncSocket类 3.3 基于CAsyncSocket类的单点聊天程序 3.4 CSocket类 3.5 基于CSocket类的多点聊天程序
3.1 MFC简介
1. MFC编程框架
使用应用程序向导(AppWizard)生成应用程序 的骨架文件(代码和资源等); 使用资源编译器直观地设计用户接口; 使用类向导(ClassWizard)将代码添加到骨架 文件; 使用编译器可以通过类库实现应用程序特定的逻 辑。
#define FD_CLOSE
0x10
0x20
他们代表MFC套接字对象可以接受并处理的六种网 络事件,当事件发生时,套接字对象会收到相应的 通知消息,并自动执行套接字对象响应的事件处理 函数。
(1)FD_READ事件通知:通知有数据可读。 (2)FD_WRITE事件通知:通知可以写数据。
(3)FD_ACCEPT事件通知:通知监听套接字有 连接请求可以接受。
3.1 MFC简介
4. MFC应用程序的执行过程
MFC程序的退出
用户单击主窗口的“关闭”按钮,发送MFC标准命令 消息ID_APP_EXIT。 主窗口处理WM_CLOSE消息。 收到WM_QUIT消息后,退出消息循环,进而退出整 个应用程序
3.2 CAsyncSocket类
MFC用类CAsyncSocket封装了Windows Sockets API,它主要是为网络程序设计人员提供的,想直 接利用Windows Sockets API的灵活性,但是又 想利用回调函数的方式来方便地处理网络事件。 在C++中,除了将插口封装成面向对象的形式外, 所做的唯一抽象是:将与插口相关的Windows消 息转换成回调函数。
3.重载套接字对象的回调函数 如果你从CAsyncSocket类派生了自己的套接 字类,你必须重载你的应用程序所感兴趣的那 些网络事件所对应的通知函数。
MFC框架自动调用通知函数,使得你可以在套 接字被通知的时候来优化套接字的行为。
3.2.4 客户端套接字对象请求连接到服务器 端套接字对象
在服务器端套接字对象已经进入监听状态 之 后 , 客 户 应 用 程 序 可 以 调 用 CAsyncSocket 类 的 Connect() 成 员 函 数 , 向服务器发出一个连接请求,
6 7 8
3.2.2 创建CasyncSocket类对象
本书将CAsyncSocket类对象称为异步套接 字对象。创建异步套接字对象一般分为两个步 骤,首先构造一个CAsyncSocket对象,再创 建该对象的底层的SOCKET句柄。
1.创建空的异步套接字对象
通过调用CAsyncSocket类的构造函数,创 建一个新的空CAsyncSocket类套接字对象, 构造函数不带参数。然后必须调用它的Create 成员函数,来创建底层的套接字数据结构,并 绑定它的地址。
BOOL Create( UINT nSocketPort=0, Int nSocketType = SOCK_STREAM, Long Ievent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT |FD_CONNECT | FD_CLOSE,
LPCTSTR lpszSocketAddress = NULL );
typedef struct tagMSG { // msg HWND hwnd; //接收消息的窗口句柄 UINT message; //消息标识(ID) WPARAM wParam; //第一个消息参数 LPARAM lParam; //第二个消息参数 DWORD time; //消息产生的时间 POINT pt; //消息产生时鼠标的位置 } MSG;
(4)FD_CONNECT事件通知:通知请求连接的 套接字,连接的要求已被处理。 (5)FD_CLOSE事件通知:通知套接字已关闭。
(6)FD_OOB事件通知:通知将有带外数据到达。
2.MFC框架对于六个网络事件的处理 当上述的网络事件发生时,MFC框架作何处理 呢?按照Windows的消息驱动机制,MFC框 架应当把消息发送给相应的套接字对象,并调 用作为该对象成员函数的事件处理函数。事件 与处理函数是一一映射的。
在afxSock.h文件中的CAsyncSocket类的声明中, 定义了与这六个网络事件对应的事件处理函数。
virtual void OnReceive(int nErrorCode); FD_READ事件 virtual void OnSend(int nErrorCode); FD_WRITE事件 virtual void OnAccept(int nErrorCode); FD_ACCEPT事件 virtual void OnConnect(int nErrorCode); FD_CONNECT事件 对应 对应 对应 对应