1、-1-本章目标 理解计算机网络编程的概念 理解TC/IP协议规范 理解Windows Sockets编程规范 掌握客户/服务器编程模型 掌握使用CAsyncSocket类进行UDP异步编程的方法 掌握使用CAsyncSocket类进行TCP异步编程的方法 掌握使用CSocket类进行TCP同步编程的方法网络编程基础网络通信基本原理 网络协议就是网络之间沟通、交流的桥梁。网络协议是计算机在网络中实现通信时必须遵守的约定,是对信息传递的速率、传输代码、代码结构、传输控制步骤、出错控制等做出规定并制定出标准-2-网络编程基础数据封装 数据打包的过程称为封装,就是在数据前面加上特定的协议头部-3-网络
2、编程基础IP地址和端口 IP地址:网络中每台计算机都必须有一个唯一的IP地址,IP地址一共32位,占4个字节,常用“点分十进制”的格式来表示,例如192.168.0.16。端口:用不同的端口号来标示同一个主机中正在进行通信的不同应用程序,端口也是一个逻辑数据,共16为,占2个字节。-4-网络编程基础套接字和字节序 套接字p 由美国伯克利大学在Unix上推出了一种应用程序访问通信协议的调用:Socket(套接字)p 套接字存在于通信区域中,通信区域也叫地址族,它是一个抽象的概念,主要用于将通过套接字通信的进程的共有特性综合在一起p 套接字通常只与同一区域的套接字交换数据(也有可能跨区域通信,但这
3、只在执行了某种转换进程后才能实现)。Windows Sockets只支持一个通信区域:网际域(AF_INET),这个域被使用网际协议簇通信的进程使用。p 套接字是一种内核对象,内核对象可以简单理解为由操作系统维护的一种数据结构。-5-网络编程基础套接字和字节序 字节序p 不同的计算机存放多字节值时,顺序可能会不同,有的是起始地址存放低位字节(低位先存),有的是起始地址存放高位字节(高位先存)。p 主机字节序:基于Intel的CPU,即常用的PC机使用的是低位先存。p 网络字节序:为保证数据的正确性,在网络协议中需要指定网络字节顺序,TCP/IP协议使用16位整数和32位整数的高位先存格式。-6
4、-网络编程基础Windows Sockets Windows Sockets是Windows下得到广泛应用的、开放的、支持多种协议的网络编程接口 从程序员的角度看Windows Socket是一组用于网络通信的可调用的API函数。-7-网络编程基础客户/服务器模式 在TCP/IP网络通信中,两个应用程序(进程)间的通信模式是客户/服务器(Client/Server)模式。一般称等待被其他进程连接的一端为服务器,而连接其他进程的一端为客户端。客户/服务器模式的建立基于以下两点:非对等作用和通信完全是异步的。该模式在操作过程中采取的是主动请示方式。-8-网络编程基础客户/服务器模式 服务器工作过程
5、:(1)打开一个通信信道(端口)并告知本地主机,它准备在某一个公认的地址(IP地址)上接受客户的连接请求;(2)进入监听状态,等待客户请求到达该端口;(3)接收到客户端服务请求,处理该请求并发送应答信号;(4)返回到第2步,等待另一客户端请求;(5)关闭服务器。客户端工作过程:(1)打开一个通信通道,并连接到服务器所在的特定端口;(2)向服务器发送服务请求报文,等待并接收应答,可继续提出请求;(3)请求结束后,关闭通信。-9-网络编程基础SOCKET API编程 Blocking和Non_blocking模式 使用Socket APIp 加载Socket Api库p 创建Socket套接字描述
6、符p 绑定Socket套接字描述符p 监听套接字p 接收数据p 接受数据并销毁相关资源p 建立客户端程序-10-网络编程基础MFC对WinSock的支持 CAsyncSocket类:用于异步非阻塞通信的Socket封装类,封装了Windows Sockets API函数,实现了TCP和UDP协议的通信操作,可方便地进行底层的网络事件通知及信息传输控制 CSocket类:是CAsyncSocket类的派生类,用于同步阻塞通信的类。该类在内部实现了同步通信机制,用于操作通讯过程的函数和父类CAsyncSocket类同名-11-网络编程基础MFC对WinSock的支持 CAsyncSocket类和C
7、Socket类的常用成员函数:虚函数虚函数函数说明函数说明适用协议适用协议Create()创建套接字,并绑定到指定IP地址和端口上TCP/UDPListen()进入监听状态TCPAccept()接受客户端连接,返回新的套接字TCPConnect()连接到服务器端TCPSend()发送数据TCPSendTo()发送数据UDPReceive()接收数据TCPRecieveFrom()接收数据UDPClose()关闭套接字TCPGetPeerName()获得另一端的IP地址和端口信息TCPGetSockName()获得本机绑定的IP地址和端口信息TCP/UDP-12-网络编程基础MFC网络编程方法
8、包含afxsock.h文件,一般在stdafx.h文件中包含该文件,。调用全局函数AfxSocketInit()初始化WinSock库。创建CAsyncSocket或CSocket类的派生类。可以覆盖OnAccept()、OnRecieve()等函数以实现事件通知效果。选择使用TCP或UDP协议进行通信。创建CAsyncSocket、CSocket类或者这两个类的派生类的对象,然后调用Create()函数创建套接字。通信完毕,调用Close()成员函数关闭Socket。-13-UDP通信编程UDP异步通信 使用CAsyncSocket类进行UDP进行异步编程的步骤:创建CAsyncSocket
9、类派生类。创建CAsyncSocket类派生类对象。调用Create()成员函数创建套接字(Socket),并将套接字绑定到本地IP地址和端口上。让应用程序进入等待接收数据状态,这一步系统自动进行。接收其他通信端发来的数据。向其他通信端发送数据。通信完毕后,关闭套接字,若是栈对象,对象在离开作用域时析构函数内自动进行关闭操作。-14-UDP通信编程创建CAsyncSocket类派生类 CAsyncSocket类是一个异步通讯类p实现了事件通知机制,通过虚函数机制通知应用程序,p为了使用这种虚函数机制,需要从CAsyncSocket派生子类,并重新定义相应的虚函数虚函数虚函数函数说明函数说明适用
10、协议适用协议OnAccept()在TCP协议通信中,当服务器端收到客户端的连接请求时,该函数被框架自动调用。在子类中覆盖该函数,可以调用Accept()成员函数接受连接TCPOnRecieve()当本机缓冲区接收到数据时,该函数自动被框架调用,一般在该函数内调用Receive()或RecieveFrom()接收数据TCP/UDPOnConnect()当通讯成功建立连接后,该函数自动被框架调用TCPOnSend()当可以发送数据时,该函数自动被框架调用,一般在该函数内调用Send()成员函数发送数据TCP/UDPOnClose()当连接被关闭时,该函数自动被框架调用TCPOnOutOfBandD
11、ata()当带外数据可用时,该函数自动被框架调用TCP-15-UDP通信编程创建套接字 CAsyncSocket类的派生类必须实例化对象,然后调用Create()成员函数创建套接字(Socket):pnSocketPort:要绑定的端口号,若是0,表明由系统自动分配一个可用端口。pnSocketType:套接字类型,SOCK_STREAM、SOCK_DGRAMplEvent:需要CAsyncSocket类关注的网络事件,plpszSocketAddress:指定要使用的本机IP地址BOOL Create(UINT nSocketPort=0,int nSocketType=SOCK_STREA
12、M,long lEvent=FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE,LPCTSTR lpszSocketAddress=NULL);-16-UDP通信编程创建套接字 lEvent是需要CAsyncSocket类关注的网络事件,这些事件正好对应了CAsyncSocket类的各个用于处理事件的虚函数,各个事件的用法如下:事件事件事件说明事件说明对应的虚函数对应的虚函数FD_ACCEPT在TCP协议通信中,当服务器端收到客户端的连接请求时,CAsyncSocket类触发该事件。OnAccept()FD_READ当本机缓冲区接收到数据
13、时,CAsyncSocket类触发该事件OnRecieve()FD_CONNECT当通讯成功建立连接后,CAsyncSocket类触发该事件OnConnect()FD_WRITE当可以发送数据时,CAsyncSocket类触发该事件OnSend()FD_CLOSE当连接被关闭时,CAsyncSocket类触发该事件OnClose()FD_OOB当有带外数据可用时CAsyncSocket类触发该事件OnOutOfBandData()-17-UDP通信编程创建套接字CAsyncSocket socket;/实例化对象/创建一个数据报(UDP)套接字,并绑定到端口3000上,/绑定到所有本机IP地址
14、上socket.Create(3000,SOCK_DGRAM);利用CAsyncSocket类创建使用UDP协议的套接字(Socket)的示例代码如下:-18-UDP接收数据/RecieveFrom()成员函数的原型如下:int ReceiveFrom(void*lpBuf,int nBufLen,CString&rSocketAddress,UINT&rSocketPort,int nFlags=0);要接收数据,只需要在其派生类中的OnRecieve()函数中调用CAsyncSocket:RecieveFrom()函数即可。其中,各参数的含义如下:lpBuf,接收数据的缓冲区地址。nBuf
15、len,接收数据的缓冲区的大小,用字节数来表示。rSocketAddress,另一端的IP地址。rSocketPort,另一端的端口。nFlags,接收数据的标志,一般都使用0。/使用RecieveFrom()函数接收数据的示例代码如下 TCHAR sBuf255=0;/定义接收数据的缓冲区CString sRemoteIP;/远端IPUINT nRemotePort;/远端端口/接收数据ReceiveFrom(sBuf,254*sizeof(TCHAR),sRemoteIP,nRemotePort);-19-UDP发送数据/该函数的原型如下:int SendTo(const void*lpB
16、uf,int nBufLen,UINT nHostPort,LPCTSTR lpszHostAddress=NULL,int nFlags=0);使用CAsyncSocket类发送数据,只需要在需要发送数据的地方直接调用SendTo()函数即可。其中,各参数的含义如下:lpBuf,要发送数据的缓冲区地址。nBufLen,要发送的数据的字节数。nHostPort,对方的端口号。lpszHostAddress,对方的IP地址。nFlags,数据发送标志,一般为0。/使用SendTo()函数发送数据的示例代码如下:CString str=_T(“hello”);m_ChatSocket.SendTo
17、(str,str.GetLength()*sizeof(TCHAR),3000,_T(“192.168.0.2”);-20-TCP通信编程创建套接字 与UDP协议不同,TCP协议通信时,首先要通过三次握手,以建立通信双方的连接。表现在编程方面,具有严格的服务器和客户端之分。服务器端需要首先处于监听状态,客户端要主动发起连接操作,服务器端接收到连接请求,要进行接受连接操作,然后才能在服务器端和客户端之间通信连接。连接建立后,TCP协议本身提供了数据确认和数据重传机制,以保证通信的可靠性。-21-TCP通信编程CAsyncSocket类服务器端 用CAsyncSocket类使用异步方式实现TCP服
18、务器端的编程方法。编程步骤如下:创建CAsyncSocket类的派生类;创建CAsyncSocket类派生类对象,作为监听套接字对象;调用Create()成员函数创建流式套接字,并将套接字绑定到本地IP地址和端口上;调用Listen()成员函数,让套接字进入监听状态;重新定义OnAccept()成员函数,在该函数内调用Accept()成员函数接受连接,并保存返回的新套接字对象。用新套接字对象调用Send()和Receive()函数与客户端通信;通信完毕调用Close()成员函数关闭新套接字对象和监听套接字对象。-22-TCP通信编程CSocket类客户端编程 使用CSocket类的同步通信机制
19、实现基于TCP的客户端程序的编程步骤如下:创建CSocket对象;调用Create()成员函数创建流式套接字,并将套接字绑定到本地IP地址和端口上;调用Connect()成员函数与服务端建立连接;连接成功后,调用Send()或()Receive()函数发送或接收数据;数据通讯完毕,调用Close()成员函数关闭套接字。-23-小结TCP/IP协议的传输层协议(TCP/UDP)、网络层协议(IP)和物理接口层,它们在操作系统内实现,不需要自己实现编写网络应用程序,有两种形式:直接使用Winsock库函数或使用MFC提供的CAsyncSocket和CSocket类在TCP/IP网络中,两个进程通信
20、的模式是客户端/服务器模式Winsock通信的基础是套接字(Socket),Socket在计算机中提供了一个通信接口,可以和任何一个具有socket的计算机通信使用UDP进行通信,发送和接收方处于相同的地位,没有主次之分,因此它的服务器端和客户端这种概念不是很明显基于UDP协议的Winscok编程步骤包括:创建套接字、绑定套接字、收发数据、关闭套接字基于TCP协议的Winscok服务器端编程步骤包括:创建套接字、绑定套接字、监听、收发数据、关闭套接字基于TCP协议的Winscok客户端编程步骤包括:创建套接字、连接服务器、收发数据、关闭套接字MFC中的CAsyncSocket类实现了Winsock的异步通信机制MFC中继承自CAsyncSocket类的CSocket类在异步通信的基础上提供了同步通信机制如果要使用异步通信,需要从CAsyncSocket或CSocket类派生自己的类如果使用同步通信,可以直接使用CSocket实例化对象-24-谢 谢 Thanks for listening.