《Socket通信(PPT36页).ppt》由会员分享,可在线阅读,更多相关《Socket通信(PPT36页).ppt(36页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Socket通信Socket通信(一)Socket相关理论(二)TCP的工作流程(三)Socket相关代码(一)Socket相关理论提到网络编程就必须说Socket。因写网络程序就必须要用Socket。对于网络编程,我们也言必称TCP/IP,似乎其它网络协议已经不存在了。对于TCP/IP,我们还知道TCP和UDP,TCP面向连接,UDP面向无连接,前者可以保证数据的正确和可靠性,后者则允许数据丢失。最后,我们还知道,在建立连接前,必须知道对方的IP地址和端口号。(一)Socket相关理论我们还知道如下几个事实:1。一个指定的端口号不能被多个程序共用。比如,如果鼠标占用了80端口,那么U盘就不能
2、用80端口了。2。很多防火墙只允许特定目标端口的数据包通过。3。服务程序在listen某个端口并accept某个连接请求后,会生成一个新的socket来对该请求进行处理。(一)Socket相关理论如果一个socket创建后并与80端口绑定后,是否就意味着该socket占用了80端口呢?如果是这样的,那么当其accept一个请求后,生成的新的socket到底使用的是什么端口呢?如果是系统会默认给其分配一个空闲的端口号,那一定不是80端口了,于是以后的TCP数据包的目标端口就不是80了-防火墙一定会阻止其通过的!(一)Socket相关理论实际上,我们可以看到,防火墙并没有阻止这样的连接,而且这是最
3、常见的连接请求和处理方式。为什么防火墙没有阻止这样的连接?它是如何判定那条连接是因为connet80端口而生成的?是不是TCP数据包里有什么特别的标志?或者防火墙记住了什么东西?(一)Socket相关理论类型流式套接字(SOCK_STREAM)-TCP提供了一个面向连接、可靠的数据传输服务,数据无差错、无重复的发送且按发送顺序接收。内设置流量控制,避免数据流淹没慢的接收方。数据被看作是字节流,无长度限制。数据报套接字(SOCK_DGRAM)-UDP提供无连接服务。数据包以独立数据包的形式被发送,不提供无差错保证,数据可能丢失或重复,顺序发送,可能乱序接收。Socket的位置传输层传输层传输层网
4、络层网络层(一)Socket相关理论在TCP和UDP同属于传输层,共同架设在IP层(网络层)之上。而IP层主要负责的是在节点之间(EndtoEnd)的数据包传送,这里的节点是一台网络设备,比如计算机。因为IP层只负责把数据送到节点,而不能区分上面的不同应用,所以TCP和UDP协议在其基础上加入了端口的信息,端口于是标识的是一个节点上的一个应用。除了增加端口信息,UPD协议基本就没有对IP层的数据进行任何的处理了。而TCP协议还加入了更加复杂的传输控制,比如滑动的数据发送窗口(SliceWindow),以及接收确认和重发机制,以达到数据的可靠传送。不管应用层看到的是怎样一个稳定的TCP数据流,下
5、面传送的都是一个个的IP数据包,需要由TCP协议来进行数据重组。所谓的端口,是为了区分不同的应用的,以在不同的IP包来到的时候能够正确转发。(一)Socket相关理论可得出信息:防火墙除了获取IP地址和端口号之外,并没有足够的信息判断TCP数据包的更多信息。所谓的端口,是为了区分不同的应用的,以在不同的IP包来到的时候能够正确转发。TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口,就像操作系统会提供标准的编程接口。TCP/IP引入了新型的“I/O”操作-Socket编程接口socket的出现只是可以更方便的使用TCP/IP协议栈而已,其对TCP
6、/IP进行了抽象,形成了几个最基本的函数接口。比如create,listen,accept,connect,read和write等等。(一)Socket相关理论如果一个程序创建了一个socket,并让其监听80端口,其实是向TCP/IP协议栈声明了其对80端口的占有。以后,所有目标是80端口的TCP数据包都会转发给该程序(这里的程序,因为使用的是Socket编程接口,所以首先由Socket层来处理)。accept函数返回的新socket其实指代的是本次创建的连接,而一个连接是包括两部分信息的,一个是源IP和源端口,另一个是宿IP和宿端口。(所谓accept函数,其实抽象的是TCP的连接建立过程
7、。)(一)Socket相关理论所以,accept可以产生多个不同的socket,而这些socket里包含的宿IP和宿端口是不变的,变化的只是源IP和源端口。这样的话,这些socket宿端口就可以都是80,而Socket层还是能根据源/宿对来准确地分辨出IP包和socket的归属关系,从而完成对TCP/IP协议的操作封装!而同时,放火墙的对IP包的处理规则也是清晰明了,不存在前面设想的种种复杂的情形。(一)Socket相关理论(二)TCP的工作流程2.1服务器端工作流程使用WSAStartup()函数检查系统协议栈安装情况使用socket()函数创建服务器端通信套接口使用bind()函数将创建的
8、套接口与服务器地址绑定使用listen()函数使服务器套接口做好接收连接请求准备使用accept()接收来自客户端由connect()函数发出的连接请求根据连接请求建立连接后,使用send()函数发送数据,或者使用recv()函数接收数据使用closesocket()函数关闭套接口(可以先用shutdown()函数先关闭读写通道)最后调用WSACleanup()函数结束WinsockSocketsAPI(二)TCP的工作流程2.2客户端程序工作流程使用WSAStartup()函数检查系统协议栈安装情况使用socket()函数创建客户端套接口使用connect()函数发出也服务器建立连接的请求(
9、调用前可以不用bind()端口号,由系统自动完成)连接建立后使用send()函数发送数据,或使用recv()函数接收数据使用closesocet()函数关闭套接口最后调用WSACleanup()函数,结束WinsockSocketsAPI2.3 服务器与客户端五元组的建立2.4TCP的程序工作流程图客户端的建立相比于服务器,客户端就简单多了,因为它只需要一个SOCKET。添加一个基于CSocket的子类Client,点击完成。这个类我们用于和客户端的连接和收发数据。然后,在主对话框的头文件中添加#includeMySocket.h,并且声明一个Cilent类m_mySocket;接着,我们得再
10、主对话框的OnInitDialog函数中添加m_mySocket.Creat();/初始化SOCKET这时候,我们可以为主对话框添加一个按钮,caption设为“连接”,用于连接。双击这个按钮,开始函数定义,在函数体中我们加入以下代码:m_mySocket.Connect(_T(127.0.0.1),8888);第一个参数表示想要连接的服务器的IP,第二个参数表示端口。现在,客户端与服务器的连接工作已经做好了,我们需要再在客户端的主对话框中添加一个按钮,caption设为“发送”,用于发送信息,在改按钮的函数中,我们添加以下代码:m_mySocket.Send(客户端发来了信息,100);/参
11、数分别表示要发送的字符串和字符串的最大长度.服务端的建立:添加一个基于CSocket的子类Socket,点击完成。这个类我们用于监听。接下来呢,我们在Socket类函数实现中点属性-重写-OnAccept。点属性-重写-OnReceive。在OnReceive函数中,我们添加以下代码:charstr100;Receive(str,100);CStringstrtest;strtest=str;AfxMessageBox(strtest);在OnAccept函数中,我们添加以下代码:SocketSocketRev=newSocket();Accept(SocketRev);这段代码的作用是在当服
12、务器监听到客户端的连接请求时,新建一个CRecv的成员,并用它来接受客户端的连接请求,也就是用它与客户端绑定。这段代码用于接收客户端发送过来的字符串,然后以MessageBox的形式显示出来。最后,在主对话框的头文件中添加#includeListen.h,并且声明一个CListen变量m_listen。然后,在主对话框的OnInitDialog函数中,添加如下代码:m_listen.Create(8888);/8888表示的是我们要监听的端口m_listen.Listen();(三)Socket相关代码 3.1 Socket基本函数的介绍3.1.1 创建套接字-Socket应用程序在使用套接口
13、通信前,必须要拥有一个套接口,使用socket()函数来给应用程序创建一个套接口。SOCKET socket(int af,/要使用的协议地址族int type,/描述套接口的类型int protocol /该套接口使用的特定协议);af参数:说明套接字接口要使用的协议地址族,地址族与协议族含义相同。如果想建立一个TCP或UDP,只能用常量。AF_INET参数表示使用互联网协议(IP)地址。Winsock还支持其他协议,但一般很少使用。type参数:描述套接口的类型,af是AF_INET的时候只能为SOCK_STREAM、SOCK_DGRAM或SOCK_RAWProtocol参数:说明该套接口
14、使用的特定协议,当协议地址族af和协议类型type确定后,协议字段可以使用的值是限定的socket()参数说明3.1.2将创建的套接口与服务器地址绑定bind()当socket()创建了一个套接口后,需要将该套接口与该主机上提供服务的某端口联系在一起,bind()函数用于完成这样的绑定。intbind(SOCKETs,/标识一个未绑定的套接口描述字conststructsockaddrFAR*name,/存储了套接口的地址信息intnamelen/地址参数(name)的长度);S参数:标识一个未绑定的套接口描述字,它是socket()函数调用成功时返回的值name参数:是一个与指定协议有关的地
15、址结构指针,存储了套接口的地址信息,Winsock中使用sockaddr_in结构指定IP地址和端口信息structsockaddr_inshortsin_family;u_shortsin_port;structin_addrsin_addr;charsin_zero8;sin_family一般为AF_INET,表示使用IP地址族;sin_port是以网络字节序表示的16位端口号;sin_addr是网络字节序的32位IP地址;sin_zero字段一般不用,用0填充namelen参数:表示地址参数(name)的长度IP地址参数为INADDR_ANY,则由系统内核来自动指定port为0,则由系统
16、自动指派一个10245000之间惟一的端口号bind()参数说明3.1.3服务器端启动监听listen()函数在一个服务器端用socket()调用成功创建了一个套接口,并用bind()函数和一个指定的地址关联后,就需要指示该套接口进入监听连接请求状态,这需要通过listen()函数来实现intlisten(SOCKETs,intbacklog);S参数:代表一个已绑定了地址,但还未建立连接的套接口描述字Backlog参数:指定了正在等待连接的最大队列长度3.1.4服务器端接受连接accept()函数在服务器端通过listen()函数调用表示服务器进入监听客户的连接请求状态,而在服务器端调用ac
17、cept()函数时表示可以接收来自客户端由connect()发出的连接请求,双方进入连接状态。SOCKETaccept(SOCKETs,/s标识一个套接字structsockaddrFAR*addr,/用来存放发出连接请求的那个客户机的IP地址信息intFAR*addrlen/指出客户套接口地址结构的长度);s参数:标识一个套接字,该套接口处于监听状态addr参数:是一个地址结构的指针,用来存放发出连接请求的那个客户机的IP地址信息addrlen参数:指出客户套接口地址结构的长度函数说明:该函数用于面向连接的服务器端,在IP协议族中,只用于TCP服务器端accept()函数参数说明3.1.5发
18、送数据-send()函数在已经建立连接的套接口上发送数据,可以使用send()函数intsend(SOCKETs,/用于标识已建立连接的套接字constcharFAR*buf,/是一个字符缓冲区,内有将要发送的数据intlen,/即将发送的缓冲区中的字符数intflags/用于控制数据传输方式);s参数:用于标识已建立连接的套接字buf参数:是一个字符缓冲区,内有将要发送的数据len参数:即将发送的缓冲区中的字符数flags参数:用于控制数据传输方式,0表示按正常方式发送数据;宏MSG_DONTROUTE说明系统目标主机就在直接连接的本地网络中,无需路由选择;MSG_OOB指出数据是按带外数据
19、发送的函数说明:send()函数适用于已建立连接的数据报或流式套接口发送数据,对于数据报类型套接口必须注意发送数据长度不大于通信子网的IP包最大长度send()函数参数说明3.1.6接收数据recv()函数对于已建立连接的套接口来说,要从套接口上接收数据,就要使用recv()函数。intrecv(SOCKETs,/已建立连接的套接口charFAR*buf,/为用于接收数据的缓冲区intlen,/为缓冲区的长度intflags/指定调用的方式);recv()函数参数说明s参数:为已建立连接的套接口buf参数:为用于接收数据的缓冲区len参数;为缓冲区的长度flags参数:指定调用的方式。0表示接
20、收的是正常数据,无特殊行为。MSG_PEEK表示会使有用的数据复制到所提供的接收端缓冲区内,但是没有从系统缓冲区中将数据删除。MSG_OOB表示处理带外数据。3.1.7关闭套接口-closesocket()函数一个套接口不再使用时一定要关闭这个套接口,以释放与该套接口关联的所有资源,包括等候处理的数据。intclosesocket(SOCKETs);参数s:表示即将被关闭的套接口3.1.8客户端请求连接connect()函数当服务器端建立好套接口并与一个本地地址绑定后,就进入监听状态,等待客户发出连接请求。在客户端套接口建立好之后,就调用connect()函数来与服务器建立连接。intconnect(SOCKETs,/将要建立连接的套接口描述字conststructsockaddrFAR*name,/是一个指向远端套接口地址结的指针intnamelen/服务器端的地址长度);s参数:将要建立连接的套接口描述字name参数:是一个指向远端套接口地址结(sockaddr_in)的指针,表示s套接口欲与其建立一条连接namelen参数:是服务器端的地址长度,即name的长度connect()函数参数说明