第 7 章 网络编程

Post on 02-Jan-2016

66 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

第 7 章 网络编程. 学习目标. 了解 网络编程的方法 理解 流式套接字和数据报套接字的区别 理解 Windows Sockets 的工作原理 了解 两种不同的通信方式 掌握 利用 MFC CSocket 类进行网络编程的方法 了解 利用 MFC CAsyncSocket 类进行网络编程的方法. 7.1 网络编程概述. 7.1.1 Windows Sockets 规范 - PowerPoint PPT Presentation

TRANSCRIPT

第 7 章 网络编程

学习目标

了解网络编程的方法

理解流式套接字和数据报套接字的区别

理解 Windows Sockets 的工作原理

了解两种不同的通信方式

掌握利用 MFC CSocket 类进行网络编程的方法

了解利用 MFC CAsyncSocket 类进行网络编程的方法

7.1 网络编程概述 7.1.1 Windows Sockets 规范

Windows Sockets (即 WinSock )规范是 90 年代初 Microsoft 公司联合其他几家大公司共同制定的—套在 Windows 下的二进制兼容网络编程接口规范。

Windows Sockets 规范制定的本意是将基础网络抽象出来 。 遵守 Windows Sockets 规范的网络软件,称之为与 windo

ws Sockets 兼容。

7.1.2 VC++ 2005 网络编程 利用 Windows Sockets 网络编程的方法 1 .利用 Windows Sockets API 进行网络编程

麻烦,但灵活

2 .利用 MFC 提供的 WinSock 类进行网络编程 在 MFC 中,提供了两个类用来实现对 Windows Socket

API 的封装,从而实现网络编程

( 1 ) CAsyncSocket 类 CAsyncSocket ,顾名思义是指采用了异步(非阻塞)套

接字的类。该类主要是提供给那些具有一定网络编程经验,希望同时拥有 Winsock API 编程的灵活性和类库编程便利性的用户的。

( 2 ) CScoket 类(阻塞) CScoket 类是 CAsyncSocket 类的派生类,该类对

Windows Sockets API 进行了更多的封装,并且利用 CArchive 类进行数据传输,从而使利用该类进行数据传输的过程与 MFC 的串行化一致。

7.2 套接字

套接字( Socket )是一个通信终结点,它是 Windows Socke

ts 应用程序用来在网络上发送或接收数据包的对象。一个套接字有自己的类型,并有一个与之相关的应用程序,它还可以有自己的名字。

7.2.1 流式套接字 使用流式套接字的过程:

在两个通信节点间建立连接 节点通过这个连接进行通信 通信完毕后取消连接

流式套接字提供了双向的数据流,并且保证数据流的传输是可靠的、有序的 ( 即:传输的数据顺序的正确性 ) 、无重复的 ( 即:数据包只被传送一次 )

最大特点是通信信息能保证按顺序无遗漏地到达目的地。

7.2.2 数据报套接字

数据报套接字也提供双向的数据传输,与流式套接字不同,它用于实现无连接的通信方式。

在传输可靠性要求不高的信息或者通信量较少的信息,则可采用数据报套接字。

7.2.3 IP 地址和端口

IP 地址是一台计算机在网络上的地址,是一个 32 位的数字 如 202.204.125.5 就是由十进制描述的一个 IP 地址

端口用于标识进程,同一机器上不同的应用程序有不同的端口,则通过“ IP 地址 + 端口”的方式可以唯一标识机器的应用程序。

7.3 Windows Sockets 的工作原理

Windows Sockets 的工作方式为客户 / 服务器模式

根据连接的方式分为

面向连接——流式套接字

无连接——数据报套接字

7.3.1 面向连接的通信方式

发送确认信息

服务器

创建并初始化套接字,

指定端口(socket)

监听客户端的请求(listen)

接受连接请求(accept)

发送接收数据(send、recv)

销毁套接字,关闭连接(closesocket)

客户端

创建并初始化套接字,

指定要连接的端口(socket)

请求建立连接(connect)

发送接收数据(send、recv)

销毁套接字,关闭连接(closesocket)

图 7-1 面向连接的通信方式

7.3.2 无连接的通信方式

发送结果

服务器

创建并初始化套接字(socket)

接受请求,进行处理(recvfrom、sendto)

销毁套接字,关闭连接(closesocket)

客户端

创建并初始化套接字(socket)

向服务器发送请求(sendto)

接收结果(recvfrom)

销毁套接字,关闭连接

(closesocket)

图 7-2 无连接的通信方式

7.5 基于 MFC 的 Windows Sockets 编程 7.5.1 编制基于流式套接字网络应用程序的步骤

1 .服务器端 服务器端应用程序的设计过程如下:

( 1 )从 CSocket 类派生两个新类,假设一个新类的名称为 CServeSocket ,另一个新类的名称为 CA

cceptSocket 。其中, CServeSocket 套接字用来监听连接请求, CAcceptSocket 套接字是真正用于与客户端进行连接、接收发送数据的套接字。

( 2 )创建一个 CServeSocket 类对象。

( 3 )调用 CSocket::Create函数创建一个 CServeSoc

ket 套接字,并指定一个端口,端口号一般要大于 102

4 。( 4 )调用 CSocket::Listen函数侦听端口。( 5 )在 CServeSocket 中添加虚函数 OnAccept 。在

OnAccept函数中为每一个连接进来的客户端创建一个新的 CAcceptSocket 类对象专门用于读写。

( 6 )在用于读写的 CSocket 派生类 CAcceptSocket

的 OnReceive函数中进行读写操作。( 7 )通讯结束时,调用读写套接字的 Close函数关闭为各个客户端分配的读写套接字。

2 .客户端客户端应用程序的设计过程如下:( 1 )创建一个 CSocket 类的派生类,用于连接和读写,假

设新类的名称为 CClientSocket 。( 2 )调用 CSocket::Create函数创建套接字。( 3 )调用 CSocket::Connect函数连接到服务器的指定端口。( 4 )调用 CSocket::Send函数发送数据,进行发送数据的操作

( 5 )在 CClientSocket 中添加虚函数 onReceive ,在该函数中进行读操作。

( 6 )在结束通讯时,调用 CSocket::Close函数关闭套接字。

7.5.2 编制基于流式套接字的网络应用程序

【例 7-1】编写两个程序,一个用于模拟服务器端的程序 M

ysev ,一个用于模拟客户端的程序 Myclient ,这个网络应用程序的功能很简单,只是实现服务器和客户端的通信。当客户端连接上服务器端时,给服务器发送消息:“服务器,你好!”,服务器向客户端发送消息:“客户端,你好!”。服务器端程序的运行结果如图 7-4所示,客户端程序的运行结果如图 7-5所示。客户端与服务器进行连接后,相互发送信息后的运行结果分别见图 7-6 和图 7-7 。

图 7-4 服务器端程序 Mysev 的运行结果 图 7-5 客户端程序 Myclient 的运行结果

图 7-6 服务器端程序接收到的信息 图 7-7 客户端程序接收到的信息

程序的实现过程如下: 1 .服务器端应用程序设计

( 1 )利用 MFC 应用程序向导新建一个基于对话框的应用程序 Mysev

图 7-8 为应用程序 Mysev添加套接字支持

( 2 )添加菜单资源 ( 3 )添加控件和关联的成员变量 ( 4 )添加套接字类型 ( 5 )建立套接字类与对话框类的关联 ( 6 )在对话框中初始化套接字并监听连接请求 ( 7 )接受连接请求 ( 8 )接收信息 ( 9 )关闭连接

2 .客户端应用程序设计 ( 1 )创建一个基于对话框的应用程序 Myclient ,在高级功能中选择“ Windows 套接字支持”,同服务器端应用程序的第一步。

( 2 )添加菜单资源 ( 3 )添加控件和关联的成员变量 ( 4 )添加套接字类型 ( 5 )建立套接字类与对话框类的关联 ( 6 )初始化套接字并建立连接 ( 7 )接收信息 ( 8 )发送消息 ( 9 )关闭连接 ( 10 )编译并运行程序

7.5.3 编制基于数据报套接字网络应用程序的步骤

基于数据报套接字的网络通信应用程序的服务器和客户端遵循同样的编程方法。

具体的编程方法如下: ( 1 )如果服务器 ( 客户程序 )需要读取客户的数据,

则创建一个 CAsyncSocket 类的派生类,并生成 该类的对象;如果服务器 ( 客户程序 )仅发送数据,则直接生成一个 CAsyncSocket 类对象。

( 2 )调用 CAsyncSocket::Socket函数创建一个数据报类型的套接字。

( 3 )调用 CAsyncSocket::SetSockOpt函数设置端口可重用。

( 4 )设置一个端口号,并调用 CAsyncSocket::Bind函数将该端口捆绑到本地地址。

( 5 )调用 CAsyncSocket:: SetSockOpt函数设置端口属性,允许传输广播信息。

( 6 )调用 CAsyncSocket::SendTo函数发送数据 ( 7 )在 OnReceive()函数中调用 ReceiveFrom函数读取客户方发

送的数据。 ( 8 )通信结束后,调用 CAsyncSocket::Close函数关闭套接字。

7.5.4 编制基于数据报套接字的网络应用程序

【例 7-2】创建两个应用程序,实现以无连接方式发送和接收数据。程序的运行结果如下图所示。

图 7-14 无连接方式发送和结束数据的结果

1 .服务器端应用程序设计 ( 1 )利用 MFC 应用程序向导新建一个基于对话框的应

用程序 MyUDPsever ,在高级功能中选择“ Windows 套接字支持”。

( 2 )修改应用程序主窗口 IDD_MYUDPSEVER_DIALOG 对话框的布局。删除原有的【取消】按钮,保留原有的【确定】按钮,将【确定】按钮的“ Default Button”属性设置为 false 。

( 3 )添加一个名为 IDD_PORT_DIALOG 的对话框,为该对话框添加相应的基于 CDialog 类的 CPortDlg 类,该对话框被用于输入通讯端口号。

( 4 )修改主窗口类 CMyUDPseverDlg ,在该类中进行通讯。

( 5 )在 CMyUDPseverDlg 类中添加WM_DESTROY类的消息处理函数 OnDestroy ,在该函数中关闭套接字

2 .客户端应用程序设计 ( 1 )利用 MFC 应用程序向导新建一个基于对话框

的应用程序 MyUDPclient ,在高级功能中选择“ Windows 套接字支持”。

( 2 )修改应用程序主窗口的 IDD_MYUDPCLIENT_DIALOG 对话框资源的布局。删除原有的【取消】按钮,保留原有的【确定】按钮

( 3 )由于本示例客户端需要从服务器读取数据,因此从 CSocket 类派生一个类 CClientSocket ,该类用于读取数据。

( 4 )添加自定义消息宏。当 CClientSocket 类对象读取了数据后,需要通过自定义消息将数据发送给应用程序主窗口。

( 5 )对 CClientSocket 类进行修改 ( 6 )创建一个 ID 为 IDD_PORT_DIALOG 的对话框,

并生成相应的基于 CDialog 类的派生类 CPortDlg 。 ( 7 )创建一个 ID 为 IDD_TRY_DIALOG 的对话框,

并生成相应的基于 CDialog 类的派生类 CTryDlg 。 ( 8 )修改MyUDPclientDlg 类,添加成员变量和成员函

数。

7.6 综合实例:聊天室 【例 7-3】创建基于客户 / 服务器模式的聊天室应用程序。

这个应用程序包括客户端的应用程序和服务器端的应用程序。

( a)服务器端 ( b)一个客户端

等待用户连接

通知所有在线用户新登陆用户信息

中转消息

当用户离线时通知所有在线用户

7.6.1 服务器端应用程序的功能介绍

7.6.2 客户端应用程序的功能介绍

获得连接参数后与服务器建立连接

发送 / 接收消息

断开时通知服务器

( 1 )利用 MFC 应用程序向导新建一个基于对话框的应用程序 C

hatRoom ,在高级功能中选择“ Windows 套接字支持”。 ( 2 )修改应用程序主窗口 IDD_CHATROOM_DIALOG 对话框

的布局。 ( 3 )添加一个头文件 tagHeader.h

( 4 )添加一个基于 CSocket 的类 CClientSocket ,用于和客户端进行数据交换。

( 5 )添加一个基于 CSocket 的类 CServerSocket ,用于接收客户端的连接。

( 6 )修改 CChatRoomDlg 类的代码 ( 7 )编译并运行程序

7.6.3 服务器端应用程序的编写过程

7.6.4 客户端应用程序的编写过程 ( 1 )利用 MFC 应用程序向导新建一个基于对话框的应用程序 ChatCli

ent ,在高级功能中选择“ Windows 套接字支持”。 ( 2 )修改应用程序主窗口 IDD_CHATCLIENT_DIALOG 对话框的布局。

( 3 )由于用户登录时需要添加服务器地址、自己的用户名等信息,所以添加一个对话框资源,其 ID 为 IDD_LOGIN_DIALOG ,并为该对话框添加基类为 CDialog 的派生类 CLoginDlg 。

( 4 )同服务器端类似,添加一个头文件 tagHeader.h

( 5 )添加一个基于 CSocket 类的派生类 CClientSocket ,用于完成数据的发送和接收。

( 6 )对类 CChatClientDlg 进行修改 。 ( 7 )编译并运行程序 。

top related