已阅读5页,还剩69页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1,要实现网络编程,有多种方法:通过WinSock、所用命名管道和邮箱、使用RPC(RemoteProcedureCall)等均可以实现在网络上的通信。本讲将介绍利用WinSock编程的两种途径:一种是通过WinSockAPI另一种是通过MFC提供的WinSock类,即CAsyncSocket和CSocket,前言,2,WindowsSocket编程原理,3,Socket概述,Socket简介WindowsSocketWinsock1.1基本APIWinsock2.0CAsyncSocketCSocket,4,什么是socket?,应用程序与网络之间的接口应用程序创建socketsocket类型决定了通信的类型可靠的vs.尽最大努力的面向连接的vs.无连接的一旦socket配置完成,应用程序就可以把数据传给socket,从而进行网络传输从socket接收数据(其他主机通过网络发送过来的)Socket在计算机中提供了一个通信接口,可以通过这个接口与任何一个具有Socket接口的计算机通信。应用程序在网络上传输,接收的信息都通过这个Socket接口来实现。,5,Socket在协议栈中的位置,Application,Transport,Network(Internet),Data-link(Host-to-Network),SocketsAPI,TCP,UDP,MyProgram,IP,6,Socket到Socket的通信,MyProgramsocket,portsTCP/UDP,IP,YourProgramsocket,portsTCP/UDP,IP,7,WindowsSocket(1),WindowsSocket是从BerkeleySocket扩展而来的,其在继承BerkeleySocket的基础上,又进行了新的扩充。这些扩充主要是提供了一些异步函数,并增加了符合Windows消息驱动特性的网络事件异步选择机制Windowssocket的版本Winsock1.1Winsock2.0,8,WindowsSocket(2),Winsock的实现方式Winsock:C-BasedAPI,与UnixCAPI类似CAsyncSocket:对WinsockAPI的简单C+封装CSocket:对Socket的高层抽象(自动处理字节顺序转换等)对象串行化CSocketFileCArchive,9,端口,Port0,Port1,Port65535,每个主机有65,536个端口一些端口被预留,用于特定的应用程序20,21:FTP23:Telnet80:HTTP参考RFC1700(大约1024个端口被预留),Socket提供了一个通过端口在网络上收发数据的接口,10,TCP/IP约定:01023为保留端口号,标准应用服务使用;1024以上是自由端口号,用户应用服务使用,端口号实质上也是操作系统标识应用程序的一种方法,其取值可由用户定义或者系统分配,11,IP地址、端口和Socket,类似公寓和邮箱你是应用程序你的公寓地址是地址你的邮箱是端口邮局是网络Socket是使你能够使用邮箱的钥匙(假设发出去的信是由你放入邮箱的)Script:Socket(48)=IP地址(32)+端口(16),12,TCP/IP应用服务工作原理,采用客户机/服务器模式服务器端启动守护进程,等待客户端的请求;服务器对应客户端的请求,派生子进程与客户进程进行数据通信,提供服务。服务器拥有全局公认的Socket,接收任何客户端的请求。,13,Socket工作原理,API函数,CAsyncSocket,CSocket,14,Socket的系统调用库函数,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),15,API的使用方法图示,16,分身有术,被动参与者step1:listen(监听连接请求)step3:accept(接受连接请求)step4:数据传输被接受的连接工作在新的Socket上旧Socket继续监听其他的主动参与者,主动参与者step2:请求并建立连接step4:数据传输,PassiveParticipant,Active1,Active2,17,#includestructsockaddr_inshortsin_family;/AF_INETunsignedshortsin_port;/16位端口号,网络字节顺序structin_addrsin_addr;/32位IP地址,网络字节顺序charsin_zero8;/保留;,Internet地址数据结构,sin_family=AF_INET选择Internet地址族,18,字节顺序,问题:不同的机器使用不同的字节顺序小头:低字节优先i386,alpha,.大头:高字节优先SunSolaris,PowerPC,.使用不同字节顺序的主机如何通过网络通信,2,28,大头主机,小头主机,WRONG!,19,解决方法:网络字节顺序,定义:主机字节顺序:主机使用的字节顺序(大头或小头)SunSolaris,PowerPC,.网络字节顺序:网络使用的字节顺序大头通过网络传输的任何信息都应该转化成网络字节顺序,接收后再转回主机字节顺序Q:Socket是否自动完成字节顺序转换?,Q:大头主机不需要转换字节顺序,而小头主机需要,如何避免写两个版本的代码?,20,字节顺序转换函数,在主机字节顺序和网络字节顺序之间转换h=主机字节顺序n=网络字节顺序l=long(4bytes),转换IP地址s=short(2bytes),转换端口号,#includeu_longPASCALFARhtonl(u_longhostlong);u_shortPASCALFARhtons(u_shorthostshort);u_longPASCALFARntohl(u_longnetlong);u_shortPASCALFARntohs(u_shortnetshort);,在大头主机上,上述函数不作任何转换在小头主机上,上述函数把字节顺序逆序Samecodewouldhaveworkedregardlessofendian-nessofthetwomachines,21,Socket的两种基本类型,SOCK_STREAMTCP可靠传输保证顺序面向连接双向,SOCK_DGRAMUDP不可靠传输无顺序保证无“连接”概念应用程序为每个包指定目的地可以发送或接收,Q:为什么需要SOCK_DGRAM类型?,22,TCP,IP,EthernetAdapter,WebServer,Port80,举例:webserver为了接收来自webclient的连接请求,webserver应做什么准备?,TCPServer,23,每个Winsock应用都必须加载WinsockDLL的相应版本,#includeintPASCALFARWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);wVersionRequested:WindowsSocketAPI提供的调用方可使用的最高版本号.高位字节指出副版本(修正)号,低位字节指明主版本号.lpWSAData:指向WSADATA数据结构的指针,用来接收WindowsSocket实现的细节.,Winsock的初始化,WSADATAwsd;if(WSAStartup(MAKEWORD(1,1),24,Web使用TCP,webserver需要创建一个SOCK_STREAM套接字,#includeSOCKETPASCALFARsocket(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_ERROR,SocketI/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),26,SocketI/O:listen(),listen表示server准备接收连接请求,#includeintPASCALFARlisten(SOCKETs,intbacklog);S:用于标识一个已捆绑未连接套接字的描述字。backlog:等待连接队列的最大长度。,ret=listen(m_hSocket,5);/第二个参数表示最多支持的客户连接数if(ret=SOCKET_ERROR)/listen失败AfxMessageBox(ListenError);returnFALSE;,27,SocketI/O:accept(),accept等待一个连接请求,#includeSOCKETPASCALFARaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);s:套接字描述字,该套接字在listen()后监听连接。addr:(可选)指针,指向一缓冲区,接收连接实体的地址。Addr参数的实际格式由套接字创建时所产生的地址族确定。addrlen:(可选)指针,指向存有addr地址长度的整形数。返回值:返回一个新的socket,其属性与s相同。若返回值h_addr_list0)-s_addr;,structhostentcharFAR*h_name;charFARFAR*h_aliases;shorth_addrtype;shorth_length;charFARFAR*h_addr_list;,33,SocketI/O:connect(),connectclient连接到server,#includeintPASCALFARconnect(SOCKETs,conststructsockaddrFAR*name,intnamelen);s:标识一个未连接套接字的描述字。name:欲进行连接的端口名。namelen:名字长度。返回值:若无错误发生,则connect()返回0。否则的话,返回SOCKET_ERROR错误。,intret=0;ret=connect(m_hSocket,(LPSOCKADDR),34,SocketI/O:send(),send向一个已连接的socket发送数据,#includeintPASCALFARsend(SOCKETs,constcharFAR*buf,intlen,intflags);s:一个用于标识已连接套接字的描述字。buf:包含待发送数据的缓冲区。len:缓冲区中数据的长度。flags:调用执行方式。返回值:若无错误发生,返回所发送数据的总数,否则返回SOCKET_ERROR错误。,if(send(m_hSocket,buf,strlen(buf),0)=SOCKET_ERROR)AfxMessageBox(Senddataerror);,35,SocketI/O:closesocket(),closesocket关闭一个socket,#includeintPASCALFARclosesocket(SOCKETs);s:一个套接字的描述字。返回值:如无错误发生,则返回0,否则返回SOCKET_ERROR错误。,36,TCPClient-Server交互流程,socket(),bind(),listen(),accept(),send(),recv(),recv(),TCPServer,closesocket(),socket(),TCPClient,connect(),send(),recv(),closesocket(),建立连接,请求数据,响应数据,文件结束标识,37,tcp_server.c,#include#defineMY_PORT3434intmain()SOCKETlisten_sock,new_sock;structsockaddr_inmy_addr;intdummy;char*buffer=Howoldareyou?n;WSADATAwsaData;WSAStartup(MAKEWORD(1,1),38,tcp_client.c,#include#include#defineMY_PORT3434intmain()SOCKETconn_sock;structsockaddr_inremote_addr;intbytes_recvd;charbuffer100;WSADATAwsaData;WSAStartup(MAKEWORD(1,1),39,UDP,IP,EthernetAdapter,NTPdaemon,UDPServer,Port123,举例:NTPdaemon为了接收来自UDPclient的服务请求,UDPserver应做什么准备?,40,SocketI/O:socket(),UDPserver必须创建一个datagramsocket,SOCKETm_hSocket;m_hSocket=socket(AF_INET,SOCK_DGRAM,0);AF_INET把socket与Internet协议族相关联SOCK_DGRAM选择UDP协议,41,把socket绑定到一个特定端口,SocketI/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(123);intret=0;interror=0;ret=bind(m_hSocket,(LPSOCKADDR),42,SocketI/O:recvfrom(),recvfrom接收一个数据报并保存源地址,#includeintPASCALFARrecvfrom(SOCKETs,charFAR*buf,intlen,intflags,structsockaddrFAR*from,intFAR*fromlen);s:标识一个套接字的描述字。buf:接收数据缓冲区。len:缓冲区长度。flags:调用操作方式。from:(可选)指针,指向装有源地址的缓冲区。fromlen:(可选)指针,指向from缓冲区长度值。返回值:若无错误发生,返回读入的字节数。如果连接已中止,返回0。否则返回SOCKET_ERROR错误。,43,SocketI/O:recvfrom(),SOCKETsrvsock;sockaddrcli;charbuf512;intcli_len=sizeof(cli);intnbytes;nbytes=recvfrom(srvsock,buf,sizeof(buf),0,(structsockaddr*),44,UDP,IP,EthernetAdapter,2UDPClients,UDPClient,ports,UDPclient如何与UDPserver通信?,45,SocketI/O:sendto(),UDPclient不与特定端口号绑定第一次调用sendto时,动态为其分配一个端口号,SOCKETclisock;charbuf512;intnbytes;sockaddr_inm_addr;m_addr.sin_family=AF_INET;m_addr.sin_addr.S_un.S_addr=inet_addr(“0”);m_addr.sin_port=htons(123);nbytes=sendto(clisock,buf,sizeof(buf),0,(structsockaddr*),46,UDPClient-Server交互流程,socket(),bind(),recvfrom(),sendto(),UDPServer,socket(),UDPClient,sendto(),recvfrom(),closesocket(),等待,直到从client接收到数据报,数据请求,数据响应,47,udp_server.c,#include#defineMY_PORT3434intmain()SOCKETudp_sock;structsockaddr_inremote_addr,local_addr;char*buffer=Howdoyoudo?;WSADATAwsaData;WSAStartup(MAKEWORD(1,1),48,udp_client.c,#include#include#defineMY_PORT3434intmain()SOCKETudp_sock;structsockaddr_inremote_addr,local_addr;intbytes_recvd,dummy;charbuffer100;WSADATAwsaData;WSAStartup(MAKEWORD(1,1),49,Winsock2.0,Winsock2.0是对winsock1.1的升级支持多种传输协议TCP/IP、IPX/SPX、ATM、NETBIOS、AppleTalk、红外线重叠I/O和事件对象服务质量套接字组共享套接字协议无关的多播通信,50,CAsyncSocket编程,51,CAsyncSocket,CAsyncSocket在低层次上封装了WinsockAPI,简化网络消息回调函数的编写。用户需要自己处理阻塞、字节顺序等问题CAsyncSocket类封装了大部分WinsockAPIServer:Create()把socket()和bind()绑定在一起Listen()Accept()Client:Create()Connect(),参见书p8位置,52,CAsyncSocket程序流程,使用CAsyncSocket的网络应用程序结构创建socketServerClient编写回调函数以便接收数据发送数据关闭socket用MFC构建使用CAsyncSocket的网络程序的步骤如右图,用AppWizard创建应用程序框架,派生CAsyncSocket的子类,重载成员函数来处理Winsock消息,等待并处理Winsock消息,激活Winsock消息,53,用AppWizard创建应用程序框架(1),在MFCAppWizard中指定支持Winsock,54,CAsyncSocketAppWizard产生的Winsock启动代码,BOOLCWinsockApp:InitInstance()if(!AfxSocketInit()AfxMessageBox(IDP_SOCKETS_INIT_FAILED);returnFALSE;.,AfxSocketInit(),WSAStartup(),调用,用AppWizard创建应用程序框架(1),55,派生CAsyncSocket类(2),CAsyncSocket派生CAsyncSocket的一个子类,CAsyncSocket,CAppSocket,derive,56,CAsyncSocket:生成的CAppSocket类(AppSocket.h),classCAppSocket:publicCAsyncSocket/Attributespublic:/Operationspublic:CAppSocket();virtualCAppSocket();/Overridespublic:/ClassWizardgeneratedvirtualfunctionoverrides/AFX_VIRTUAL(CAppSocket)/AFX_VIRTUAL/Generatedmessagemapfunctions/AFX_MSG(CAppSocket)/NOTE-theClassWizardwilladdandremovememberfunctionshere./AFX_MSG/Implementationprotected:;,派生CAsyncSocket类(2),57,添加处理Winsock事件的代码(3),58,classCAppSocket:publicCAsyncSocket./ClassWizardgeneratedvirtualfunctionoverrides/AFX_VIRTUAL(CAppSocket)public:virtualvoidOnReceive(intnErrorCode);/AFX_VIRTUAL.;,AppSocket.h,voidCAppSocket:OnReceive(intnErrorCode)/TODO:Addyourspecializedcodehere/and/orcallthebaseclassCAsyncSocket:OnReceive(nErrorCode);,AppSocket.cpp,添加处理Winsock事件的代码(3),59,激活Winsock事件(4),CAsyncSocket:激活Winsock事件重载通知函数,BOOLCAsyncSocket:AsyncSelect(longlEvent);lEvent=FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE,onReceive()当有数据要接收时的调用onSend()准备好发送数据时调用onAccept()可以接受连接请求时调用onConnect()当建立连接时调用onClose()当socket关闭时调用,60,CAsyncSocket的成员函数,Accept接收连接AsyncSelect设置socket的事件通知Bind为socket绑定地址Close关闭socket.Connect建立连接IOCtl控制socket的模式Listen监听连接请求Receive从socket接收数据ReceiveFrom接收数据报,并保存源地址Send向建立连接的socket发送数据SendTo向特定地址发送数据ShutDown禁止socket上的Send和/或Receive调用,61,CAsyncSocket构造一个CAsyncSocket对象Create创建一个socket.Attach把一个sockethandle关联到一个CAsyncSocket对象Detach取消sockethandle与一个CAsyncSocket对象之间的关联FromHandle给定一个sockethandle,返回一个指向CAsyncSocket对象的指针GetLastError得到最后一个错误操作的错误状态GetPeerName得到建立连接的socket的地址GetSockName得到一个socket的名字GetSockOpt得到一个socket的选项SetSockOpt设置一个socket的选项,CAsyncSocket的成员函数,62,CSocket编程,63,WinSock,CAsyncSocket(MFC),与物理网络的距离,CSocket(MFC),CSocket简介,64,CSocketServer,CSocketClient,ServSocket.Listen();,socket.Connect(“aHost”,8080);,使用CSocket的过程(1),65,建立连接后的一对CSocket可以
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 浅谈通感的修辞手法
- 浅议公民道德建设的着力点
- 2025年毕业论文书面评语
- 标准论文格式及范文
- 毕业论文书写规范与打印要求-论文格式-
- 应用数学毕业论文选题题目
- 工程合同一般都是几份(3篇)
- 试论语法研究的三个平面
- 医用X射线诊断设备产品技术审评规范
- 西北工业大学论文格式
- 2025-2031年中国动压油膜滑动轴承行业市场深度研究及投资策略研究报告
- 治未病科管理制度
- 《伊斯兰文化圈》课件
- DB32T 4116-2021 里氏硬度计法建筑结构钢抗拉强度现场检测技术规程
- 员工人事档案
- 工程联系单(适用于向施工单位监理单位下发的联系单)
- 职业学校三方协议书填写模板
- 自动跟踪定位射流灭火系统技术标准
- 类器官技术在疾病建模中的应用
- 影响静脉穿刺成功率PDCA原因分析鱼骨图冰山图对策拟定
- 物流园区及货运站场规划设计方案
评论
0/150
提交评论