您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 国内外标准规范 > 第6章 网络编程(VC)
第6章网络编程(VC)重庆三峡学院数学与计算机科学学院2020/2/242本章主要内容1、套接字编程原理2、基本的WindowsSocketsAPI编程3、MFC下的Socket编程的类4、一个使用CSocket类的网络通信实例2020/2/2431.套接字编程原理一个完整的网络通信进程需要由两个进程组成,并且只能用同一种高层协议。也就是说,不可能通信的一端用TCP,而另一端用UDP。一个完整的网络通信需要一个五元组来标识:协议、本地地址、本地端口号、远端地址、远端端口号。2020/2/2441.1Client/server通信模型在客户/服务器模式中我们将请求服务的一方称为客户端(client),将提供某种服务的一方称为服务器(server)。一个服务程序通常在一个众所周知的地址监听对服务的请求,也就是说服务进程一直处于休眠状态,直到一个客户端对这个服务的地址提出了连接请求。2020/2/245在这个时刻,服务程序被“惊醒”并且为客户端提供服务—对客户端的请求作出适当的反应。虽然基于连接的服务是设计客户端/服务器应用程序的标准,但有些服务也是可以通过无连接的接口提供的。2020/2/246客户端/服务器的请求/响应过程示意图如下所示。图1客户/服务器通信模型2020/2/247通过上面的分析,我们不难理解一个一个完整的网络应用程序包括客户端和服务器两个部分。客户端与服务器进程的作用是非对称的,因此编码不同。服务进程一般是等待客户端请求而启动的,只要系统运行,该服务进程一直存在,直到终止或强迫终止。2020/2/2481.2WindowsSockets规范WindowsSockets规范是90年代初Microsoft公司联合其他几家大公司共同制定的一套在Windows下的二进制兼容网络编程接口规范。它以U.C.Berkeley大学BSDUNIX中流行的Socket接口为基础,主要在其上扩充了一组针对Windows的扩展库函数,增加了符合Windows消息驱动特性的网络事件异步选择机制,以使程序员能够充分利用Windows消息驱动机制进行编程。2020/2/249WindowsSockets的用途是将基础网络抽象出来,这样,您不必对网络非常了解,并且您的应用程序可在任何支持套接字的网络上运行。它为应用程序开发者定义了一套简单统一的API,并让各家网络软件供应商共同遵守。2020/2/2410MFC提供了两个类用以封装WindowsSocketsAPI。一个是CAsyncSocket类,它主要是提供给那些具有一定网络编程经验,希望同时拥有SocketAPI编程的灵活性和类库编程便利性的开发者。另一个是CSocket类,它由CAsyncSocket类派生,它具有更高的抽象化,致力于简化网络编程所需的操作。2020/2/24111.3套接字(Socket)1.3.1套接字定义套接字,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端面点。简单的说,套接字就是通信两方的一种约定,用套接字中的相关函数来完成通信过程。2020/2/2412使用套接字的应用程序间通信模型如图2所示。应用程序A套接字A应用程序B套接字B图2套接字通信模型2020/2/24131.3.2分类可用的套接字类型有以下两种:流式套接字数据报套接字2020/2/24141.3.2.1流式套接字流式套接字提供没有记录边界的数据流,即字节流。字节流能确保以正确的顺序无重复地被送达。2020/2/2415创建并初始化套接字监听来自客户机的请求接受连接请求接收数据发送数据关闭连接创建并初始化套接字请求建立连接发送数据接收数据关闭连接服务器客户机图3流式套接字(有连接通信)编程2020/2/24161.3.2.2数据报套接字数据报套接字支持面向记录的数据流,但不能确保能被送达,也无法确保按照发送顺序或不重复。2020/2/2417创建并初始化套接字监听来自客户机的请求进行处理发送结果给客户端关闭连接创建并初始化套接字向服务器发出请求接收结果关闭连接服务器客户机图4数据报套接字(无连接通信)编程2020/2/24181.3.3套接字的作用套接字的作用非常大,至少在下面三种通信上下文中如此:客户端/服务器模型。对等网络方案,如聊天应用程序。通过让接收应用程序将消息解释为函数调用来进行远程过程调用(RPC)。2020/2/24191.3.4端口与地址在网络上,一个套接字的标识主要借助于地址和端口来描述。套接字的地址指该套接字所在计算机的网络地址,可以为域名或IP地址的形式。通常,创建套接字时不必指明网络地址,只有在拥有多个网络地址的机器时,才需要显式指定一个网络地址。2020/2/2420同一机器上可以运行多个网络应用程序,每个应用程序都有自己的套接字用以进行网络通信,此时如果只有地址标识套接字,则当一个通信包到达机器时,将无法确定究竟是哪个应用程序的套接字需要接收此信息。由此增加了端口的概念,以协助区分同一机器上不同应用程序的套接字。2020/2/2421端口用于标识进程,同一机器上不同的网络应用程序各有不同的端口,这样,通过“网络地址+端口号”的标识方法,便唯一标识了机器上的应用程序了。某些端口是专门为公共服务保留的(ftp:21,http:80),除非程序是要提供这些服务,否则应尽量避免使用这些端口。一般来说,端口1024以前的端口号都是系统保留的或是作为公共服务的,应尽量选择大于1024的端口号,以避免冲突。2020/2/24222、基本的WindowsSocketsAPI编程需要在程序中添加下面的包含语句:#includewinsock2.h使用VC++编译时需添加编译链接依赖项ws2_32.lib库协议寻址2020/2/24233、MFC下的Socket编程的类MFC提供了两个类来支持套接字编程,它们是CAsyncSocket类和CSocket类。2020/2/24243.1CAsyncSocket类CAsyncSocket类一对一地封装WindowsSocketAPI。CAsyncSocket类适合那些对网络通信细节很了解,且希望利用回调的便利通知网络事件的程序员使用。如果想利用WindowsSockets方便地处理MFC应用程序中的多个网络协议,而又不想放弃灵活性,可以考虑使用CAsyncSocket。2020/2/2425CAsyncSocket类是MFC在方便性与灵活性中的一种折衷方案。MFC提供了一个类用以保留网络编程的灵活性,而方便性则由下面要讲到的CSocket类来提供。2020/2/24263.2CSocket类CSocket类是CAsyncSocket类的派生类,它致力于提供比CAsyncSocket类更高的抽象性,使得网络编程变得简单方便。CSocket类支持流方式和数据报方式,但一般情况下用的更多的是流方式的数据通信。2020/2/2427在流方式的通信模式下,CSocket类通常会与CArchive类结合,以串行化的方式发送和接收数据,这使得网络编程变得像读写文件一样简单了。CArchive类扮演的是一个数据缓冲区的角色,它通过CSocketFile类与一个套接字相联系。只要建立了两者的联系,然后往“数据缓冲区”装入数据与取出数据就完成了。2020/2/2428发送数据与接收数据的示意图如图5所示。接收数据发送数据数据CArchive对象CSocketFile类对象CSocket类对象CSocket类对象CSocketFile类对象CArchive对象数据接收数据发送数据图5流方式下数据的流向图2020/2/2429由图5可以看出只要建立好套接字跟CArchive类对象的关联,则发送和接收数据时,只需要对CArchive对象进行操作,从而可以利用此类对象优良的串行化功能,十分方便地实现发送和接收数据。2020/2/24304、一个使用CSocket类的网络通信实例本例采用CSocket编程模型建立一个聊天程序的简单实例。建立项目时注意选上“Windows套接字”复选框。2020/2/24314.1服务器端应用程序设计(ServerDemo)1)界面2020/2/2432控件类型控件IDCaption属性控件变量变量类型列表框IDC_Log无m_LogCtrlCListBox编辑框IDC_Message无m_MsgCtrlCEdit按钮IDC_Send发送M_SendCtrlCButton静态控件IDC_STATIC记录无无静态控件IDC_STATIC待发消息无无各控件属性如下列表框控件IDC_Log属性“sort”值为false,属性“HorizontalScroll”值为true。按钮IDC_Send属性Disable值为true。2020/2/24332)定义CSocket类的派生类CServSocket和CRecvSocket。从CSocket编程模型知道,服务器端需要两种套接字,一个用来侦听连接请求,一个用来与请求连接的套接字建立连接。因此,为程序添加两个CSocket派生类:SServSocket和CRecvSocket,它们与对话框类密切配合,共同完成程序所要求实现的功能。2020/2/24343)建立套接字与对话框类的关联在程序中,对话框类要用到套接字类,而套接字类在响应某些消息,如在函数OnAccept、OnReceive中进行处理时,也要改变对话框的某些控件状态,以反映给用户这些事情的发生。2020/2/2435这里存在着两个类相互使用的情况,把套接字类对象定义成对话框类的成员变量,同时在套接字类中也把对话框类定义为成员变量。如何实现这样的用法呢?在对话框类头文件中加入套接字头文件的声明,然后在套接字类头文件中加入对话框类头文件的声明,这样的做法显然行不通。2020/2/2436具体做法应该如下:首先,在ServerDemoDlg.h中加入套接字类头文件的声明,语句#pragmaonce的后面加入如下语句:#includeServSocket.h#includeRecvSocket.h2020/2/2437然后在该文件中为CServerDemoDlg类增加两个公有成员变量,语句如下:CServSocket*ServSock;CRecvSocket*RecvSock;这样在对话框类中就可以使用套接字类了。2020/2/2438继续在套接字类中加入对话框类信息。首先,在ServSocket.h文件的开头,语句#pragmaonce的后面加入如下语句:classCServerDemoDlg;2020/2/2439然后,在该文件中为CServSocket类添加一个公有成员变量和一个构造函数:CServSocket(CServerDemoDlg*Dlg);CServerDemoDlg*m_Dlg;2020/2/2440接着在ServSocket.cpp文件中添加新的构造函数的实现,并添加一条关于ServerDemoDlg.h文件的预编译声明,代码如下:#include“ServerDemoDlg.h”CServSocket::CServSocket(CServerDemoDlg*Dlg){m_Dlg=Dlg;}2020/2/2441这样,在套接字类中也可以通过成员变量使用对话框了。使用同样的方法对CRecvSocket类进行设置,使其也可以通过成员变量使用对话框。2020/2/24424)为套接字添加串行化读写信息的功能。在服务器端的两个套接字中,只有CRecvSocket套接字是真正与客户端套接字建立连接,发送与接收数据的。因此,我们只为该类添加串行化读写信息功能。2020/2/2443在RecvSocket.h文件中为类CRecvSocket添加三个公有成员变量。CSocketFile*m_File;CArchive*m_ArIn;
本文标题:第6章 网络编程(VC)
链接地址:https://www.777doc.com/doc-3803764 .html