版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第25章 网络编程简介这里所说的网络主要是指因特网(Internet)。本章先介绍网络与编程的一些基本概念,然后重点讲解套接字(Socket)和WinInet的MFC编程,最后简介ASP.NET的Web编程。25.1 网络与编程本节先介绍网络的概念和发展简史,再给出两种主流的分层网络模型,然后讨论与网络编程有关的接口和技术等基本内容。25.1.1 网络我们所说的网络(network)一般指计算机网络,它是一种由多台独立自主的计算机通过软硬件互连,以实现资源共享和信息交换的系统。提供资源或信息的计算机和软件被称为服务器,请求和使用资源或信息的计算机和软件被称为客户端。如网站是Web服务器,浏览器
2、就是Web客户端。依据通信的距离和范围,网络可以分成(十米几公里的)局域网(Local Area Network,LAN,如校园网)、(几十公里内的)城域网(Metropolitan都市/大城市 Area Network,MAN,如3G网)和(百公里外的)广域网(Wide Area Network,WAN,如因特网)。局域网有多种拓扑结构(参见图25-1),目前使用最广泛的是采用总线型拓扑结构的以太网(Ethernet),它是由美国施乐(Xerox)公司帕洛阿尔托研究中心(PARC)的Bob Metcalfe于1976年发明的(1979年他离开了施乐创建了3COM公司),以太网使用CSMA/C
3、D(载波监听多路访问及冲突检测技术)技术,并以10M/S的速率运行在多种类型的电缆上。以太网与IEEE 802.3系列标准相似。网络的核心是协议(Protocol)。25.1.2 因特网因特网(Internet,网际网/互联网) 的前身是1969年底启用的ARPANet (Advanced Research Projects Agency Network,美国国防部高级研究计划署网络,阿帕网),由Bob Taylor和Larry Roberts等人主持研制。1973年底,Robert E. Kahn和Vinton Cerf提出了基于包交换的两个网络协议IP(Internet Protocol,
4、 网际协议)和TCP(Transmission Control Protocol,传输控制协议),1983年元旦ARPANet启用TCP/IP协议集。1986年,ARPANet的主干网被NSFNet(National Science Foundation Network,美国国家科学基金会网络)接替,并改名为Internet(因特网),1991年起对社会开放。25.1.3 万维网图25-1 Tim Berners-Lee1990年10月在CERN(Conseil Europeen pour la Recherche Nucleaire,欧洲粒子物理研究所)工作的Tim Berners-Lee(
5、参见图25-1)提出了因特网应用层的两个协议:用于描述网页的HTML(HyperText Markup Language,超文本标记语言)和用于传输网页文档和各种资源数据的HTTP(Hypertext Transfer Protocol,超文本传输协议),创立了万维网(World Wide Web,WWW,环球网),一般简称为Web(蜘蛛网),Web很快成为因特网的主体。1993年初,美国Illinois(伊利诺)大学的硕士研究生Marc Anderressen与Eric Bina合作在位于该校内的NCSA(National Center for Supercomputing Applicat
6、ions美国超级计算应用中心)开发出支持内嵌图像的网页浏览器马赛克(Mosaic),1994年10月Anderressen等人创办的网景公司Netscape推出了Navigator浏览器,得到广泛使用,大大推动了互联网的普及。1995年微软公司从伊利诺大学购得马赛克技术,并在此基础上开发出IE(Internet Explorer,因特网探索者)浏览器,随Windows 95免费推出。被微软公司挤垮的网景公司于1998年11月被AOL公司收购,并于2003年7月成立了非盈利的Mozilla基金会,在其资助下于2004年11月9日推出了基于Mosaic的Firefox(火狐)浏览器。1994年10
7、月Berners-Lee创立了万维网联盟(World Wide Web Consortium,W3C),负责万维网的管理和技术标准的制定。1998年2月W3C推出了划时代的XML(eXtensible Markup Language,可扩展标记语言),2000年1月又推出了用来替代HTML的XHTML(Extensible HTML,扩展的HTML)。传统的万维网Web正在向新的万维网One Web过渡,参见图25-2。图25-2 Web体系结构的发展其中:l URL(Uniform Resource Locator,统一资源定位符) 在因特网的Web服务程序上用于指定信息位置的表示方法,如h
8、ttp://。l URI(Uniform Resource Identifier,统一资源标识符) = URL + URN。l URN(Uniform Resource Name,统一资源命名) 使用urn方案的URI,不一定意味着有确定的资源可用。如urn:isbn:。l IRI(Internationalized Resource Identifiers,国际化资源标识符) URI的国际化,支持Unicode。25.1.3 IP网络的分层与协议这里的IP网络是指基于因特网协议套件(TCP/IP协议栈)的网络,包括:因特网(Internet)、城域网(Metro
9、politan Area Network,MAN)和内部网(Intranet)等。为了便于分析和管理,一般将通信网络抽象为若干层。主要有ISO(和IEC共同)制定的7层参考模型(Reference Model)ISO/OSI(国际标准,失败,主要用于理论研究)和因特网5层参考模型TCP/IP协议栈(实事标准,成功,应用十分广泛)。参见表25-1和图25-2&3。表25-1 ISO/OSI 7层参考模型OSI模型数据单元层功能主机层数据7. 应用对应用的网络过程6. 表示数据表示与加密5. 会话主机间通信段4. 传输端到端连接与可靠性 (TCP)介质层包/数据报3. 网络路径确定与逻辑寻址 (I
10、P)帧2. 数据链接物理寻址(MAC & LLC)位1. 物理介质,信号与二进制传送其中:l ISO(International Organization for Standardization,国际标准化组织) 由153个国家的国家标准学会联合组成的一个非政府国际组织,总部(中央秘书处)设在瑞士的日内瓦,负责制定适应商业和广泛社会需要的各种国际标准,网址为。l IEC(International Electrotechnical Commission,国际电工技术委员会) 一个成立于1906年6月的国际标准化权威组织,属于联合国的甲级咨询机构,负责制定关于电
11、工电子各方面的标准,有42个会员国,总部也设在瑞士的日内瓦,网址为http:/www.iec.ch。l OSI(Open Systems Interconnection,开放系统互连) 一种通信协议的7层抽象的参考模型,其中每一层执行某一特定任 务。该模型的目的是使各种硬件在相同的层次上相互通信。对应的国际标准为:ISO 7498:1984、ISO/IEC 7498-14: 1994、1989、1989、1997)。l MAC(Media Access Control,介质访问控制) 数据链路层的子层,提供寻址和信道访问的控制机制,位于物理层和逻辑链路层之间。l LLC(Logical Lin
12、k Control,逻辑链路控制)数据链路层的上部子层,在MAC层上传输的多路复用和分离协议,提供流量和差错控制。ISO/OSI 7层参考模型 因特网5层参考模型(及协议) 应用层(Application) 应用层 (HTTP/HTML、FTP、SMTP/POP3/IMAP、) 表示层(Presentation) 会话层(Session) 传输层(Transport) 传输层 (TCP/UDP) 网络层(Network) 互连网层 (IP/ICMP/IGMP) 数据链路层(Data-link) 网络接口层 (ARP/RARP) 物理层(Physical) 物理层图25-2 OSI与因特网参考模
13、型的层次对应关系其中:l ARP(Address Resolution Protocol,地址解析协议) 计算机用来匹配IP地址到硬件地址的协议。计算机调用ARP广播一个请求,目标计算机应答该请求。l RARP(Reverse Address Resolution Protocol, 逆向地址解析协议) 计算机系统在自举时获取IP地址的协议。l IP(Internet Protocol, 网际协议) 定义互联网上包的格式与路由包到其目的地之机制。l ICMP(Internet Control Message Protocol,互连网控制消息协议)提供网络层的控制手段和差错报告。l IGMP(I
14、nternet Group Management Protocol,互连网组管理协议) 用来管理组播的,它是参加组播的主机与路由器之间交换组员信息的协议。不过,组播目前存在多个组的地址冲突问题,而且,现有的路由器一般不支持组播。l TCP(Transmission Control Protocol,传输控制协议) 为应用程序提供访问面向连接的通信服务,可靠、控制流量。特点:面向连接、累计确认与超时重传(保证数据传输的可靠性)、拥塞控制(基于滑动窗口协议)、报头变长(24B)。l UDP(User Datagram Protocol,用户数据报协议) 为用户提供无连接的服务,高效但不可靠,主要用
15、于传输多媒体数据。特点:无连接、无差错控制(不重传)、报头中的校验和可选(可不计算和存储)、报头定长(8B)。l FTP(File Transfer Protocol , 文件传输协议) 因特网上管理文件传输的通讯协议,用于从一台计算机到另一台计算机传送完整的文件。l SMTP(Simple Message Transfer Protocol, 简单邮件传输协议) 用于电子邮件的传输。l POP3((Post Office Protocol,邮局协议第三版) 提供用户计算机对(本地邮件服务器中的)电子邮箱进行远程存取的脱机协议。l IMAP(Internet Message Access Pr
16、otocol,因特网消息访问协议)提供用户计算机对(本地邮件服务器中的)电子邮箱进行远程操作的联机协议。图25-3 IP网络模型25.1.4 因特网编程通用的因特网编程,一般采用传统的套接字(Sockets)网络API,在Windows平台中对应的是Winsock。微软还自己开发了用于因特网应用层的编程接口WinInet。1Sockets和Winsock因特网(Internet)最初是基于Unix的,而Sockets(套接字/插座)是Unix第一个支持TCP/IP协议栈的网络API,最早于1982年8月随4.2 BSD版Unix推出,常被称为Berkeley sockets(伯克利套接字)。U
17、nix的BSD(Berkeley Software Distribution,美国加州大学 伯克利分校软件分发)版,是由Sun公司的创始人之一兼首席技术官Bill Joy(比尔乔伊)于1977年在伯克利分校读研期间自己开发的。Sockets也是由他编写的。图25-4 Bill JoyWinsock(Windows Sockets API)是从Sockets移植过来的TCP/IP编程的低级Windows API,由JSB公司的Martin Hall、Sun公司的Mark Towfiq和Geoff Arnold、微软公司的Henry Sanders和J Allard等人共同开发。Winsock的版
18、本有:l 1.0(1992年6月,微软不支持)l 1.1(1993年1月,微软在Windows for Workgroups 3.1的扩展包中支持,该扩展包也是Windows 95和Windows NT 3.x的组成部分)l 2.0(1994年,未公开发布)l 2.1.0(1996年1月,首个公开发布的Winsock 2规范,微软在Windows 95的扩展包中支持,该扩展包也是Windows 98和Windows NT 4.0及后续Windows版本的组成部分)l 2.2.0(1996年5月,去掉了对16位Windows应用程序的支持) l 2.2.1(1997年5月)l 2.2.2(199
19、7年8月)在Windows中,除了可以直接用Winsock API进行C/C+编程外,还可以用Winsock的MFC和.NET BCL封装进行面向对象和组件的编程。MFC封装的Winsock类有:基本的异步套接字类CAsyncSocket和简单的套接字类CSocket。为了使用Winsock编程,程序员得详细了解因特网应用层的具体协议内容。2WinInet使用Winsock编程,程序员必须与基本的网络通信打交道,还必须详细了解因特网应用层协议的具体内容,包括对话模式、命令的组成和格式、命令发送的顺序等等。为了方便因特网应用程序的编写,微软在Winsock之外,还自己开发了用于因特网应用层编程的
20、接口WinInet(Win32 Internet Extensions,32位Windows的因特网扩展)。WinInet的优点:l 支持高速缓存似IE,将HTML和其他因特网文件放入本地磁盘的特定目录,下次可直接加载该文件,而不是重复从因特网下载l 安全支持基本的质询/响应鉴别和SSL(Secure Socket Layer安全套接字层)l 采用缓冲I/Oread函数不返回值,可读取单独的文本行l 简单可使用状态回调函数OnStatusCallBack来对UI更新和注销;调用一个函数CInternetSession:OpenURL就可以找到IP地址、建立连接并准备好文件读取l 友好可分析和格
21、式化报头,访问已经被移动的新位置处的服务器和文件MFC也包括了对WinInet的封装,提供了一些十分好用的类与全局函数,包括对HTTP、FTP、Gopher等协议的处理。3WCF4Web开发ASP.NET25.2 MFC套接字编程MFC提供了两个套接字类CAsyncSocket和Csocket,它们封装了Winsock 1.0版的函数,可方便地编写因特网程序。CAsyncSocket提供异步读写(网络通信),而CSocket则提供同步读写(网络通信),后者是前者的派生类,它们图25-5 MFC套接字类都是MFC的基类CObject的派生类,参见图25-5。基类CAsyncSocket提供全面的
22、由事件驱动的Socket通信能力,你可以在派生的套接字类中响应这些事件。CSocket类是CAsyncSocket的派生类,封装和简化了其基类的某些功能,是Winsock的高层接口。由于Windows程序是基于消息机制的,MFC的套接字类也提供消息编程,可以通过它们的成员函数AsyncSelect来选择感兴趣的事件。25.2.1 编程过程为了使建立的项目支持Winsock,需要在MFC应用程序向导的高级功能页中选中Windows套接字复选框。1初始化Winsock环境在使用MFC 的套接字类之前,必须为应用程序初始化Winsock环境,这只需在项目的应用类的初始化实例函数InitInstanc
23、e中调用全局函数AfxSocketInit:BOOL AfxSocketInit( WSADATA* lpwsaData = NULL );该函数以WSADATA结构:struct WSAData WORD wVersion; / 套接字规范的(最低)板本/ 低/高字节为主/次版本号,如257:1.1 WORD wHighVersion; / 套接字规范的最高版本,如514:2.2 char szDescriptionWSADESCRIPTION_LEN+1; / 描述串/ 如“WinSocket 2.0” char szSystemStatusWSASYSSTATUS_LEN+1; / 系统
24、状态串/ 如“Running” unsigned short iMaxSockets; / 单个进程可打开的最大套接字数,如32767 unsigned short iMaxUdpDg; / 可收发的UDP报文的最大字节数,如65467 char FAR * lpVendorInfo; / 指向厂商指定数据结构的指针,WinSock不支持; / 其中的iMaxSockets和iMaxUdpDg用于兼容1.1版,在2.0版中不用作为可选参数,能得到当前计算机的Winsock的版本等信息。一般不需要,如:BOOL CSockApp:InitInstance() if (!AfxSocketInit
25、()AfxMessageBox(IDP_SOCKETS_INIT_FAILED);return FALSE;若在项目创建过程中,选中了“Windows套接字”复选框,则MFC会在程序中自动添加上述代码。2创建套接字为了使所建立的应用程序可以使用套接字,还必须在项目的应用类中声明一个MFC套接字派生类的类变量,如:class CSockApp : public CWinApp private:CAsyncSocket m_sSock;在使用该对象之前,必须调用其Create成员函数来构造具体的套接字:BOOL Create( UINT nSocketPort = 0, int nSocketTy
26、pe = SOCK_STREAM, long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE, LPCTSTR lpszSocketAddress = NULL );客户端一般不需要任何输入参数,但对服务器端的网络应用程序,需要指定监听端口号(nSocketPort),如:l 客户端:m_sSock.Create();l 服务器端:m_sServSock.Create(4000);其中,参数nSocketType可取值为SOCK_STREAM(对应于传输层面向连接的TCP协议)和SOCK_DGRA
27、M(对应于传输层无连接的UDP协议);参数lpszSocketAddress为网络地址,当计算机上有多个网卡时有用,单网卡可用(本机的IP地址)。TCP和UDP的端口是一个16位无符号整数,取值范围为065535。其中,01023为著名端口、102449151为已注册端口、4915265535为动态或私有端口。下面是若干常用的缺省TCP/UDP端口:HTTP(80)、HTTPS(443)、FTP(21)、SMTP(25)、POP3(110)、DNS(53)、SQL(118/156)、Login(513)、Echo(7)、Socket proxy(1080)、Web proxy
28、(8080)。3打开连接打开一个网络连接需要三个步骤:l 服务器端调用Listen函数监听连接请求:BOOL Listen( int nConnectionBacklog = 5 ); / 待连接的队列长度,最大为5l 客户端调用Connect函数发出连接请求:BOOL Connect( LPCTSTR lpszHostAddress, UINT nHostPort );l 服务器端调用Accept函数接受连接请求:virtual BOOL Accept( CAsyncSocket& rConnectedSocket,SOCKADDR* lpSockAddr = NULL,int* lpSoc
29、kAddrLen = NULL );如:if (m_sServSock.Listen() . else .if (m_sSock.Connect(L, 4000) . else .if (m_sServSock.Accept(m_sSock) . else .若连接成功或失败,CAsyncSocket都会激发一个事件通知应用程序,而CSocket类在连接成功或失败之前不会返回。4发送/接收消息可以通过套接字发送和接收任何类型的数据,需要一个缓冲区来存放待发或刚接收到的数据。发送数据使用Send函数:virtual int Send( const void* lpBuf, in
30、t nBufLen, int nFlags = 0 ); / 返回发送的数据总量接收数据则使用Receive函数:(在接收完数据之前不会返回)virtual int Receive( void* lpBuf, int nBufLen, int nFlags = 0 ); / 返回接收到数据量出错都返回SOCKET_ERROR。如:l 发送:CString strMessage;int iLen, iError;.iLen = strMessage.GetLength();iError = m_sSock.Send(LPCSTR(strMessage), iLen);if (iError = S
31、OCKET_ERROR) . else .l 接收:char *pBuf = new char1025;int iBufSize = 1024;int iRcvd;CString strRecvd;iRcvd = m_sSock.Receive(pBuf, iBufSize);if (iRcvd = SOCKET_ERROR) . else pBufiRcvd = NULL; / 分隔垃圾数据strRecvd = pBuf;.5关闭连接应用程序在完成与对方的所有通信知后,应该调用Close函数来关闭连接:服务器监听客户端发送连接请求服务器接受连接请求收发信息关闭连接virtual void C
32、lose( );6网络通信过程网络的通信过程与打电话类似,先须接电话的人可感知电话的响铃或震动(服务器监听),打电话的人拨号(客户端发送连接请求),接电话的人接听(服务器接受连接请求),双方通话(客户端与服务器相互发送和接收信息),挂断电话(客户端或服务器关闭连接),参见图25-6。25.2.2 编程实例为了说明Winsock的基本功能,我们创建一个基于对话框的简单MFC网络程序,它可同时作为服务器与客户端使用(两份运行实例)。服务器负责监听,客户端请求连接,在建立连接后的两端发送和接收消息,程序将把消息显示在对话框中的列表中。1创建项目创建一个名为Sock的MFC应用程序项目,在在MFC应用
33、程序向导的“应用程序类型”页中,设置“基于对话框”,并且去选“使用Unicode库”复选框,参见图25-6。 图25-6 创建基于对话框且不使用Unicode库的MFC项目Sock另外需要在MFC应用程序向导的高级功能页中选中Windows 套接字复选框(参见图25-7),其余采用默认设置,按完成创建项目。图25-7 在向导对话框的高级功能页中设置支持Windows套接字2设计对话框资源在MFC生成的ID为IDD_SOCK_DIALOG的对话框资源中,添加如图25-8所示的各种控件。图25-8 Sock程序的对话框资源其中,l 套接字类型中客户端和服务器单选钮的ID分别为IDC_RCLIENT
34、和IDC_RSERVER,并设置前一个单项钮的Group属性为True;l 服务器地址和服务端口编辑框的ID分别为IDC_ESERVADDR和IDC_ESERVPORT;l 连接按钮的ID为IDC_BCONNECT;l 关闭按钮的ID为IDC_BCLOSE,设置其Disabled属性为True;l 消息编辑框的ID为IDC_EMSG,也设置其Disabled属性为True;l 发送按钮的ID为IDC_BSEND,还是设置其Disabled属性为True;l 已发送和已接收列表框的ID分别为IDC_LSENT和IDC_LRECVD,设置它们的Sort和Tabstop属性都为False,并在它们的
35、Selection属性的下拉式列表中,将Single改为None。(目的是让它们只能依次显示条目,而不被排序和选中)3对话框类添加成员变量用类向导在MFC自动创建的对话框类CSockDlg中为控件添加成员变量,参见表25-2。表25-2 为对话框类CSockDlg添加的控件变量控件控件ID控件变量名分类类型“客户端”单选钮IDC_RCLIENTm_iTypeValueint“服务器地址”编辑控件IDC_ESERVADDRm_strAddrValueCString“服务器端口”编辑控件IDC_ESERVPORTm_iPortValueint“连接”按钮IDC_BCONNECTm_ctlConne
36、ctControlCButton“消息”编辑控件IDC_EMSGm_strMessageValueCString“已发送”列表框IDC_LSENTm_ctlSentControlCListBox“已接收”列表框IDC_LRECVDm_ctlRecvdControlCListBox4修改连接按钮的文字为了使程序可同时作为服务器与客户端使用,必须根据套接字类型来改变连接按钮上的文字客户端为连接/ 服务器端为监听。为此,可给IDC_RCLIENT添加BN_CLICKED事件的消息响应函数OnSockType(自己修改后的函数名):void CSockDlg:OnSockType() / TODO:
37、在此添加控件通知处理程序代码UpdateData(TRUE); / 使控件与变量同步/ 我们在哪种模式?if (m_iType = 0)/ 在按钮上设置合适的文本m_ctlConnect.SetWindowText(连接(&O);elsem_ctlConnect.SetWindowText(监听(&I);把同一函数OnSockType也添加给IDC_RSERVER的BN_CLICKED事件的消息响应,这可以通过在CSockDlg类代码文件的消息映射代码段中,在语句行:ON_BN_CLICKED(IDC_RCLIENT, &CSockDlg:OnSockType)之下添加:ON_BN_CLICK
38、ED(IDC_RSERVER, &CSockDlg:OnSockType)来完成。可编译测试一下单击单项钮的效果。5创建CAsyncSocket的派生类为了能处理套接字事件,需要创建一个从CAsyncSocket派生的类,如名为CMySocket。具体步骤是:l 在项目窗口中选中项目名,按鼠标右键打开弹出式菜单,选添加/类子菜单项,在弹出的添加类对话框中选MFC/MFC类项,按添加钮,参见图25-9。图25-9 为Sock项目添加MFC类l 在弹出MFC类向导中,键入类名CMySocket,选择基类CAsyncSocket,参见图25-10。图25-10 键入类名CMySocket并选择基类C
39、AsyncSocket在该类的头文件中添加指向对话框的私有数据成员:private:CDialog* m_pWnd;并添加公用成员函数SetParent的原型:public:void SetParent(CDialog *pWnd);在该类的代码文件的尾部添加对应的函数体:void CMySocket:SetParent(CDialog *pWnd) m_pWnd = pWnd; / 设置成员指针利用属性窗口,为派生的套接字类CMySocket添加重写型消息响应函数OnAccept(参见图25-11),并在该函数中调用对话框类的同名函数:图25-11 添加重写型消息响应void CMySock
40、et:OnAccept(int nErrorCode) if (nErrorCode = 0) / 无错误,调用对话框的OnAccept函数(CSockDlg*)m_pWnd)-OnAccept();类似地,为CMySocket类添加OnConnect、OnClose、OnReceive和OnSend等重写型消息响应函数,并在其中调用对话框类的对应同名函数。为了在CMySocket类的代码中使用对话框类CSockDlg,还需将对话框的头文件包含在套接字派生类的代码文件MySocket.cpp中:#include SockDlg.h6对话框类的套接字类变量与初始化将套接字派生类的头文件包含在对话
41、框的头文件SockDlg.h中:#include MySocket.h定义私有成员变量:private:CMySocket m_sListenSocket, m_sConnectSocket;BOOL m_bConnected;它们分别代表服务器端的监听套接字和服务器与客户端的连接套接字(用于来回发送/接收消息),及是否已经连接。在对话框的初始化函数中添加代码如下:BOOL CSockDlg:OnInitDialog() CDialog:OnInitDialog();. ./ TODO: 在此添加额外的初始化代码/ 初始化控件变量m_iType = 0; / 默认类型为客户端程序m_strAd
42、dr = loopback; / 特殊的服务器名 = (本机IP地址)m_iPort = 4000; / 服务端口号m_bConnected = FALSE; / 初始时未连接/ 更新控件,FALSE=对话框初始化数据,TRUE=从对话框获取数据UpdateData(FALSE);/ 设置套接字对话框指针m_sConnectSocket.SetParent(this); / 设置连接套接字的父窗口为对话框m_sListenSocket.SetParent(this); / 设置监听套接字的父窗口也为对话框return TRUE; / 除非将焦点设置到控件,否则返回 TRUE7
43、连接应用程序用户单击IDC_BCONNECT连接按钮(表示连接或监听)后,应该禁用对话框上部的所有控件,以免用户修改相应的设置。然后调用套接字的Create函数创建具体对象,最后调用Connect或Listen函数建立监听或连接。为此,可为IDC_BCONNECT按钮添加BN_CLICKED事件处理函数:void CSockDlg:OnBnClickedBconnect() / TODO: 在此添加控件通知处理程序代码UpdateData(TRUE); / 使变量与控件同步/ 禁用连接和类型控件GetDlgItem(IDC_BCONNECT)-EnableWindow(FALSE);GetDl
44、gItem(IDC_ESERVADDR)-EnableWindow(FALSE);GetDlgItem(IDC_ESERVPORT)-EnableWindow(FALSE);GetDlgItem(IDC_RCLIENT)-EnableWindow(FALSE);GetDlgItem(IDC_RSERVER)-EnableWindow(FALSE);/ 以客户还是服务器方式运行?if (m_iType = 0) / 客户,创建缺省套接字m_sConnectSocket.Create();/ 打开与服务器的连接m_sConnectSocket.Connect(m_strAddr, m_iPort)
45、;else / 服务器,创建绑定指定端口的套接字m_sListenSocket.Create(m_iPort);m_sListenSocket.Listen(); / 监听连接请求为了完成连接,还需要为对话框类添加下列公用成员函数,包括函数原型:public:void OnAccept();void OnConnect();和函数体:void CSockDlg:OnAccept() if (m_bConnected) / 已连接CAsyncSocket sRjctSock; / 创建拒绝套接字/ 创建要发送的消息CString strMsg = Too many connections, tr
46、y again later.; m_sListenSocket.Accept(sRjctSock); / 接受对拒绝套接字的使用/ 发送拒绝消息sRjctSock.Send(LPCTSTR(strMsg), strMsg.GetLength();sRjctSock.Close(); / 关闭套接字else / 未连接/ 接受连接请求m_sListenSocket.Accept(m_sConnectSocket);m_bConnected = TRUE;/ 激活消息和发送控件GetDlgItem(IDC_EMSG)-EnableWindow(TRUE);GetDlgItem(IDC_BSEND)
47、-EnableWindow(TRUE);void CSockDlg:OnConnect() / 激活消息、发送和关闭控件GetDlgItem(IDC_EMSG)-EnableWindow(TRUE);GetDlgItem(IDC_BSEND)-EnableWindow(TRUE);GetDlgItem(IDC_BCLOSE)-EnableWindow(TRUE);8发送和接收为发送按钮添加鼠标单击事件处理函数void CSockDlg:OnBnClickedBsend() / TODO: 在此添加控件通知处理程序代码int iLen, iSent; / 设置保存消息长度的变量/ 使控件与变量同
48、步UpdateData(TRUE);/ 有消息要发送?if (m_strMessage != ) / 获取消息长度iLen = m_strMessage.GetLength();/ 发送消息iSent = m_sConnectSocket.Send(LPCTSTR(m_strMessage), iLen);/ 是否发送成功?if (iSent = SOCKET_ERROR) MessageBox(发送失败!, 套接字错误);else / 添加消息到列表框m_ctlSent.AddString(m_strMessage);/ 使控件与变量同步UpdateData(FALSE);添加公用成员函数的
49、原型:public:void OnReceive();void OnSend();与函数体:void CSockDlg:OnReceive() char *pBuf = new char1025;int iBufSize = 1024;int iRcvd;CString strRecvd;/ 接收消息iRcvd = m_sConnectSocket.Receive(pBuf, iBufSize);/ 是否成功收到消息?if (iRcvd = SOCKET_ERROR) MessageBox(接收失败!, 套接字错误);else / 截去消息串尾pBufiRcvd = NULL;/ 复制消息到串
50、变量strRecvd = pBuf;/ 添加消息到已接收列表框m_ctlRecvd.AddString(strRecvd);/ 使变量与控件同步UpdateData(FALSE);void CSockDlg:OnSend() 9终止连接为对话框类添加公用成员函数的原型:public:void OnClose();和函数体:void CSockDlg:OnClose() / 关闭已连接的套接字m_sConnectSocket.Close();m_bConnected = FALSE;/ 禁用消息发送控件GetDlgItem(IDC_EMSG)-EnableWindow(FALSE);GetDlg
51、Item(IDC_BSEND)-EnableWindow(FALSE);GetDlgItem(IDC_BCLOSE)-EnableWindow(FALSE);/ 是否运行在客户模式?if (m_iType = 0) / 是,激活连接配置控件GetDlgItem(IDC_BCONNECT)-EnableWindow(TRUE);GetDlgItem(IDC_ESERVADDR)-EnableWindow(TRUE);GetDlgItem(IDC_ESERVPORT)-EnableWindow(TRUE);GetDlgItem(IDC_RCLIENT)-EnableWindow(TRUE);Get
52、DlgItem(IDC_RSERVER)-EnableWindow(TRUE);和关闭按钮的事件处理函数:void CSockDlg:OnBnClickedBclose() / TODO: 在此添加控件通知处理程序代码/ 调用OnClose函数OnClose();10运行l 运行程序的第1个实例,先在套接字类型中选服务器单选钮,再按监听钮;l 运行程序的第2个实例,按连接钮;在其消息编辑框中输入字符串,如Hello!,然后按发送钮;l 在第1个实例的已接收列表框中会显示从客户端收到的消息;也可以在其消息编辑框中输入字符串,如OK,然后按发送钮;l 在第2个实例的已接收列表框中会显示从服务器端收
53、到的消息。运行结果参见图25-12。 a) 程序的第1个实例(服务器端)b) 程序的第2个实例(客户端)图25-12 运行Sock程序进行C/S通信也可以与因特网上的其他应用层服务器通信,参见图25-13。 a) 访问FTP服务器b) 访问SMTP服务器图25-13 运行Sock程序的客户端访问FTP和SMTP服务器11过程框图Sock程序的编程过程见图25-14。套接字派生类 对话框类创建基于对话框、不使用Unicode、支持套接字的MFC应用程序项目Sock编辑对话框资源(添加控件,设置ID)添加若干控件变量添加异步套接字派生类CMySocket添加重写型消息响应函数(调用对话框的同名函数
54、)添加若干自定义消息响应函数添加单项钮的消息响应(修改连接按钮的文本串)在初始化对话框响应函数中进行初始化添加发送按钮的消息响应(发送消息)添加关闭按钮的消息响应(关闭连接或监听)添加CMySocket对象添加SetParent成员函数(设置对话框为父窗口)图25-14 Sock程序的过程框图25.3 WinInet编程简介为了进一步方便因特网应用程序的编写,MFC还包括了对WinInet API的封装,提供了对HTTP、FTP、Gopher(囊地鼠,一种基于菜单驱动的因特网信息查询工具)等应用层协议的编程接口。25.3.1 WinInet的MFC类图25-15是与WinInet相关的MFC类的层次结构图。图25-15 MFC的WinInet类层次结构其中:l CInternetSession(因特网会话类)为WinInet的基本类,用于所有的WinIn
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 惠州购房协议书
- 2026年广告营销API 对接合同
- 骨髓瘤化疗的内分泌管理
- 2024防透平油泄漏处置方案
- 2026年建筑工程施工标准化操作流程单选题
- 2025-2030中国职业教育实训设备健康与安全标准行业市场分析及产品研发与创新能力提升报告
- 2025-2030中国矿泉水资源分布与可持续开发策略研究报告
- 2025-2030中国皮肤外用激素类药物安全性再评价对市场影响研究
- 浙江建设投资集团校招试题及答案
- 招聘杂工面试题及答案
- 吊车参数表完整版本
- 如何提高初中生的地理图解能力
- 中职形体仪态训练的课程设计
- 劳动教育第一课 整理衣物有条理
- YY/T 1888-2023重组人源化胶原蛋白
- 连锁酒店提高好评数量技巧
- JJG 556-2011轴向加力疲劳试验机
- GB/T 37827-2019城镇供热用焊接球阀
- GB/T 24533-2019锂离子电池石墨类负极材料
- 古代伊斯兰的设计艺术课件
- 注射用辅酶I(康复)课件
评论
0/150
提交评论