socket编程概述.

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

1要实现网络编程,有多种方法:通过WinSock、所用命名管道和邮箱、使用RPC(RemoteProcedureCall)等均可以实现在网络上的通信。本讲将介绍利用WinSock编程的两种途径:一种是通过WinSockAPI另一种是通过MFC提供的WinSock类,即CAsyncSocket和CSocket前言2WindowsSocket编程原理3Socket概述Socket简介WindowsSocketWinsock1.1基本APIWinsock2.0CAsyncSocketCSocket4什么是socket?应用程序与网络之间的接口应用程序创建socketsocket类型决定了通信的类型•可靠的vs.尽最大努力的•面向连接的vs.无连接的一旦socket配置完成,应用程序就可以把数据传给socket,从而进行网络传输从socket接收数据(其他主机通过网络发送过来的)Socket在计算机中提供了一个通信接口,可以通过这个接口与任何一个具有Socket接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个Socket接口来实现。5Socket在协议栈中的位置ApplicationTransportNetwork(Internet)Data-link(Host-to-Network)SocketsAPITCPUDPMyProgramIP6Socket到Socket的通信MyProgramsocketportsTCP/UDPIPYourProgramsocketportsTCP/UDPIP7WindowsSocket(1)WindowsSocket是从BerkeleySocket扩展而来的,其在继承BerkeleySocket的基础上,又进行了新的扩充。这些扩充主要是提供了一些异步函数,并增加了符合Windows消息驱动特性的网络事件异步选择机制Windowssocket的版本Winsock1.1Winsock2.08WindowsSocket(2)Winsock的实现方式Winsock:C-BasedAPI,与UnixCAPI类似CAsyncSocket:对WinsockAPI的简单C++封装CSocket:对Socket的高层抽象(自动处理字节顺序转换等)•对象串行化•CSocketFile•CArchive9端口Port0Port1Port65535每个主机有65,536个端口一些端口被预留,用于特定的应用程序20,21:FTP23:Telnet80:HTTP参考RFC1700(大约1024个端口被预留)Socket提供了一个通过端口在网络上收发数据的接口10TCP/IP约定:0—1023为保留端口号,标准应用服务使用;1024以上是自由端口号,用户应用服务使用端口号实质上也是操作系统标识应用程序的一种方法,其取值可由用户定义或者系统分配11IP地址、端口和Socket类似公寓和邮箱你是应用程序你的公寓地址是地址你的邮箱是端口邮局是网络Socket是使你能够使用邮箱的钥匙(假设发出去的信是由你放入邮箱的)Script:Socket(48)=IP地址(32)+端口(16)12TCP/IP应用服务工作原理采用客户机/服务器模式服务器端启动守护进程,等待客户端的请求;服务器对应客户端的请求,派生子进程与客户进程进行数据通信,提供服务。服务器拥有全局公认的Socket,接收任何客户端的请求。13Socket工作原理API函数CAsyncSocketCSocket14Socket的系统调用库函数1、创建套接字Sockid=Socket(af,type,protocol)2、建立地址和套接字的联系bind(sockid,localaddr,addrlen)3、服务器端侦听客户端的请求listen(Sockid,quenlen)4、建立服务器/客户端的连接(面向连接TCP)客户端请求连接Connect(sockid,destaddr,addrlen)服务器端等待从编号为Sockid的Socket上接收客户连接请求newsockid=accept(Sockid,Clientaddr,paddrlen)5、发送/接收数据面向连接:send(sockid,buff,bufflen)recv()面向无连接:sendto(sockid,buff,…,addrlen)recvfrom()6、释放套接字close(sockid)15API的使用方法图示16分身有术被动参与者step1:listen(监听连接请求)step3:accept(接受连接请求)step4:数据传输被接受的连接工作在新的Socket上旧Socket继续监听其他的主动参与者主动参与者step2:请求并建立连接step4:数据传输PassiveParticipantl-socka-sock-1a-sock-2Active1socketActive2socket17#includewinsock.hstructsockaddr_in{shortsin_family;//AF_INETunsignedshortsin_port;//16位端口号,网络字节顺序structin_addrsin_addr;//32位IP地址,网络字节顺序charsin_zero[8];//保留};Internet地址数据结构sin_family=AF_INET选择Internet地址族18字节顺序问题:不同的机器使用不同的字节顺序•小头:低字节优先i386,alpha,...•大头:高字节优先SunSolaris,PowerPC,...使用不同字节顺序的主机如何通过网络通信128.119.40.12128119401212.40.119.1281281194012大头主机小头主机19解决方法:网络字节顺序定义:主机字节顺序:主机使用的字节顺序(大头或小头)SunSolaris,PowerPC,...网络字节顺序:网络使用的字节顺序–大头通过网络传输的任何信息都应该转化成网络字节顺序,接收后再转回主机字节顺序Q:Socket是否自动完成字节顺序转换?Q:大头主机不需要转换字节顺序,而小头主机需要,如何避免写两个版本的代码?20字节顺序转换函数在主机字节顺序和网络字节顺序之间转换‘h’=主机字节顺序‘n’=网络字节顺序‘l’=long(4bytes),转换IP地址‘s’=short(2bytes),转换端口号#includewinsock.hu_longPASCALFARhtonl(u_longhostlong);u_shortPASCALFARhtons(u_shorthostshort);u_longPASCALFARntohl(u_longnetlong);u_shortPASCALFARntohs(u_shortnetshort);在大头主机上,上述函数不作任何转换在小头主机上,上述函数把字节顺序逆序Samecodewouldhaveworkedregardlessofendian-nessofthetwomachines21Socket的两种基本类型SOCK_STREAMTCP可靠传输保证顺序面向连接双向SOCK_DGRAMUDP不可靠传输无顺序保证无“连接”概念–应用程序为每个包指定目的地可以发送或接收Appsocket321Dest.Appsocket321D1D3D2Q:为什么需要SOCK_DGRAM类型?22TCPIPEthernetAdapterWebServerPort80举例:webserver为了接收来自webclient的连接请求,webserver应做什么准备?TCPServer23每个Winsock应用都必须加载WinsockDLL的相应版本#includewinsock.hintPASCALFARWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);wVersionRequested:WindowsSocketAPI提供的调用方可使用的最高版本号.高位字节指出副版本(修正)号,低位字节指明主版本号.lpWSAData:指向WSADATA数据结构的指针,用来接收WindowsSocket实现的细节.Winsock的初始化WSADATAwsd;if(WSAStartup(MAKEWORD(1,1),&wsd)!=0){returnFALSE;}24Web使用TCP,webserver需要创建一个SOCK_STREAM套接字#includewinsock.hSOCKETPASCALFARsocket(intaf,inttype,intprotocol);af:一个地址格式描述。type:新套接字的类型描述。protocol:套接字所用的协议。如调用者不想指定,可用0。SocketI/O:socket()SOCKETm_hSocket;m_hSocket=socket(AF_INET,SOCK_STREAM,0);AF_INET把socket与Internet协议族相关联SOCK_STREAM选择TCP协议25把socket绑定到一个特定端口intPASCALFARbind(SOCKETs,conststructsockaddrFAR*name,intnamelen);s:标识一未捆绑套接字的描述字。name:赋予套接字的地址。返回值:没有错误,bind()返回0,否则返回SOCKET_ERRORSocketI/O:bind()sockaddr_inm_addr;m_addr.sin_family=AF_INET;m_addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);m_addr.sin_port=htons(80);intret=0;interror=0;ret=bind(m_hSocket,(LPSOCKADDR)&m_addr,sizeof(m_addr));if(ret==SOCKET_ERROR){AfxMessageBox(BindingError);//绑定错误returnFALSE;}26SocketI/O:listen()listen表示server准备接收连接请求#includewinsock.hintPASCALFARlisten(SOCKETs,intbacklog);S:用于标识一个已捆绑未连接套接字的描述字。backlog:等待连接队列的最大长度。ret=listen(m_hSocket,5);//第二个参数表示最多支持的客户连接数if(ret==SOCKET_ERROR){//listen失败AfxMessageBox(ListenError);returnFALSE;}27SocketI/O:accept()accept等待一个连接请求#includewinsock.hSOCKETPASCALFARaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);s:套接字描述字,该套接字在listen()后监听连接。addr:(可选)指针,指向一缓冲区,接收连接实体的地址。Addr参数的实际格式由套接字创建时所产生的地址族确定。addrlen:(可选)指针,指向存有addr地址长度的整形数。返回值:返回一个新的socket,其属性与s相同。若返回值0,则表明发生了错误。28SocketI/O:accept()#includewinsock.hSOCKETsocket;structsockaddrcli;intcli_len=sizeof(cli);socket=accept(m_hSocket,&cli,&cli_len);if(socket0){AfxMessageBox(Lis

1 / 74
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功