第三章 MFC Winsock类编程
- 格式:ppt
- 大小:1.07 MB
- 文档页数:16
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编程,我们可以实现简单的网络聊天程序。
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 编程(一)实验指导(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简介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: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的一个类库。
第三章 MFC 应用程序概述第3章 MFC 应用程序概述Microsoft Windows 是微软公司推出的一个应用于微机上的具有图形用户界面的多任务和多窗口的操作系统。
Windows 应用程序也称为窗口应用程序,所有的窗口应用程序都有着相同的窗口风格和菜单结构,用户界面友好,方便用户操作。
本章从剖析窗口应用程序的基本结构入手,继而介绍使用MFC 类库开发的应用程序框架结构,并介绍窗口应用程序运行的核心机制-消息映射。
学习了本章,你将对MFC 应用程序框架结构和运行机制有个整体的了解,为后面进入窗口应用程序开发打下良好的基础。
3.1 窗口应用程序概述窗口应用程序的开发一般采用可视化的面向对象的开发,可选择的窗口应用程序开发语言有Visual C++、Visual Basic 、Visual Java 、Dephi 等等。
无论采用哪一种开发语言,首先要了解窗口应用程序的基本机制。
3.1.1 窗口编程基础窗口应用程序运行于Windows 操作系统,Windows操作系统是一个多任务操作系统,因此窗口应用程序的组成,支持技术,基本运行机制等与DOS 应用程序有着本质的区别。
在学习开发窗口应用程序之前,先要对窗口应用程序有一个概念上的了解。
1. 窗口窗口是应用程序与用户进行交互的界面,应用程序通过窗口传递信息给用户,同样用户通过窗口输入数据,发布命令给应用程序。
Windows 界面包含了丰富的标准用户界面元素,包括窗口、图标、菜单、滚动条、对话框、控件和消息框等。
用户使用这些界面元素可以方便的与应用程序进行交互,一个典型的窗口外观如图3-1所示。
垂直滚动条控制菜单栏标题栏菜单栏关闭按钮最小化按钮最大化按钮客户区VC++6简明教程图3-1 Windows应用程序窗口组成在Windows编程中,各种窗口、菜单、按钮、对话框及程序模块等Windows的规范部件是按“对象”来组织的。
为了提高开发窗口应用程序的效率,微软公司为用户提供了大量能创建上述标准元素的API函数和C++类,并且以Windows API函数库和C++类库的形式提供给用户,以充分满足构成应用程序操作界面的需要。