1、网络通信
互联网本质就是一系列的网络通信,互联网协议的功能是定义计算机如何介入internet,以及介入internet的计算机通信的标准。互联网协议按照功能不同分为osi7层或tcp/ip五层或tcp/ip四层
1、osi七层协议
应用层 | DHCP·DNS·FTP·Gopher·HTTP·IMAP4·IRC·NNTP·XMPP·POP3·SIP·SMTP·SNMP·SSH·TELNET·RPC·RTCP·RTP·RTSP·SDP·SOAP·GTP·STUN·NTP·SSDP |
表示层 | HTTP/HTML·FTP·Telnet·ASN.1 (具有表示层功能) HTTPS |
会话层 | ADSP·ASP·H.245·ISO-SP·iSNS·NetBIOS·PAP·RPC· RTCP·SMPP·SCP·SSH·ZIP·SDP (具有会话层功能) |
传输层 | TCP·UDP·TLS·DCCP·SCTP·RSVP·PPTP |
网络层 | IP(IPv4·IPv6)·ICMP·ICMPv6·IGMP·IS-IS·IPsec·BGP·RIP·OSPF·ARP·RARP |
数据链路层 | Wi-Fi(IEEE 802.11)·WiMAX(IEEE 802.16)·ATM·DTM·令牌环·以太网路·FDDI.帧中继·GPRS·EVDO·HSPA·HDLC·PPP·L2TP·ISDNSTP |
物理层 | 以太网路卡·调制解调器·电力线通信(PLC)·SONET/SDH (光同步数字传输网)·G.709 (光传输网络)·光导纤维·同轴电缆·双绞线 |
各层的功能简述: 【1】物理层:主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换),这一层的数据叫做比特。 【2】数据链路层:定义了如何让格式化数据以进行传输,以及如何让控制对物理介质的访问,这一层通常还提供错误检测和纠正,以确保数据的可靠传输。 【3】网络层:在位于不同地理位置的网络中的两个主机系统之间提供连接和路径选择,Internet的发展使得从世界各站点访问信息的用户数大大增加,而网络层正是管理这种连接的层。 【4】传输层:定义了一些传输数据的协议和端口号(WWW端口80等),如:TCP(传输控制协议,传输效率低,可靠性强,用于传输可靠性要求高,数据量大的数据),UDP(用户数据报协议,与TCP特性恰恰相反,用于传输可靠性要求不高,数据量小的数据,如QQ聊天数据就是通过这种方式传输的), 主要是将从下层接收的数据进行分段和传输,到达目的地址后再进行重组,常常把这一层数据叫做段。 【5】会话层:通过传输层(端口号:传输端口与接收端口)建立数据传输的通路,主要在你的系统之间发起会话或者接受会话请求(设备之间需要互相认识可以是IP也可以是MAC或者是主机名)。 【6】表示层:可确保一个系统的应用层所发送的信息可以被另一个系统的应用层读取。例如,PC程序与另一台计算机进行通信,其中一台计算机使用扩展二一十进制交换码(EBCDIC),而另一台则使用美国信息交换标准码(ASCII)来表示相同的字符。如有必要,表示层会通过使用一种通格式来实现多种数据格式之间的转换。 【7】应用层: 是最靠近用户的OSI层,这一层为用户的应用程序(例如电子邮件、文件传输和终端仿真)提供网络服务。 各层中涉及的协议的简单解释: 应用层 ·DHCP(动态主机分配协议) · DNS (域名解析) · FTP(File Transfer Protocol)文件传输协议 · Gopher (英文原义:The Internet Gopher Protocol 中文释义:(RFC-1436)网际Gopher协议) · HTTP (Hypertext Transfer Protocol)超文本传输协议 · IMAP4 (Internet Message Access Protocol 4) 即 Internet信息访问协议的第4版本 · IRC (Internet Relay Chat )网络聊天协议 · NNTP (Network News Transport Protocol)RFC-977)网络新闻传输协议 · XMPP 可扩展消息处理现场协议 · POP3 (Post Office Protocol 3)即邮局协议的第3个版本 · SIP 信令控制协议 · SMTP (Simple Mail Transfer Protocol)即简单邮件传输协议 · SNMP (Simple Network Management Protocol,简单网络管理协议) · SSH (Secure Shell)安全外壳协议 · TELNET 远程登录协议 · RPC (Remote Procedure Call Protocol)(RFC-1831)远程过程调用协议 · RTCP (RTP Control Protocol)RTP 控制协议 · RTSP (Real Time Streaming Protocol)实时流传输协议 · TLS (Transport Layer Security Protocol)安全传输层协议 · SDP( Session Description Protocol)会话描述协议 · SOAP (Simple Object Access Protocol)简单对象访问协议 · GTP 通用数据传输平台 · STUN (Simple Traversal of UDP over NATs,NAT 的UDP简单穿越)是一种网络协议 · NTP (Network Time Protocol)网络校时协议 传输层 ·TCP(Transmission Control Protocol)传输控制协议 · UDP (User Datagram Protocol)用户数据报协议 · DCCP (Datagram Congestion Control Protocol)数据报拥塞控制协议 · SCTP(STREAM CONTROL TRANSMISSION PROTOCOL)流控制传输协议 · RTP(Real-time Transport Protocol或简写RTP)实时传送协议 · RSVP (Resource ReSer Vation Protocol)资源预留协议 · PPTP ( Point to Point Tunneling Protocol)点对点隧道协议 网络层 IP(IPv4 · IPv6) Internet Protocol(网络之间互连的协议) ARP : Address Resolution Protocol即地址解析协议,实现通过IP地址得知其物理地址。 RARP :Reverse Address Resolution Protocol 反向地址转换协议允许局域网的物理机器从网关服务器的 ARP 表或者缓存上请求其 IP 地址。 ICMP :(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。 ICMPv6: IGMP :Internet 组管理协议(IGMP)是因特网协议家族中的一个组播协议,用于IP 主机向任一个直接相邻的路由器报告他们的组成员情况。 RIP : 路由信息协议(RIP)是一种在网关与主机之间交换路由选择信息的标准。 OSPF : (Open Shortest Path First开放式最短路径优先). BGP :(Border Gateway Protocol )边界网关协议,用来连接Internet上独立系统的路由选择协议 IS-IS:(Intermediate System to Intermediate System Routing Protocol)中间系统到中间系统的路由选择协议. IPsec:“Internet 协议安全性”是一种开放标准的框架结构,通过使用加密的安全服务以确保在 Internet 协议 (IP) 网络上进行保密而安全的通讯。 数据链路层 802.11 · 802.16 · Wi-Fi · WiMAX · ATM · DTM · 令牌环 · 以太网 · FDDI · 帧中继 · GPRS · EVDO · HSPA · HDLC · PPP · L2TP · ISDN 物理层 以太网物理层 · 调制解调器 · PLC · SONET/SDH · G.709 · 光导纤维 · 同轴电缆 · 双绞线
我们写的程序属于应用层
每层运行常见的物理设备
· 一组电信号构成一个数据包,叫做帧 · 每一数据帧分成:包头head和数据data两部分 head包含:固定18个字节 · 发送者/源地址,6个字节 · 接收者/目标地址 6个字节 · 数据类型 6个字节 data包含:最短46个字节,最长1500字节 ·数据包的具体内容 head长度 + data长度 = 最短64字节,最长1518字节,超过最大限制就分片发送
mac地址:
head中包含的源和目标地址由来:etnernrt国定接入internet的设备必须具备网卡,发送端和接收端的地址便是指网卡的地址,即mac地址
mac地址:每块网卡出厂时都被烧制成世界上唯一的mac地址,长度为48为2进制,通常由12为16进制数表示(前六位时厂商编号,后六位时流水线好)
广播:
有了mac地址,同一网络内的两台主机就可以通信了(一台主机哦那个过arp协议获取另外一台主机的mac'地址)。ethernet(以太网)采用最原始的方式广播进行通信。
③网络层
由来:有了ethernet、mac地址、广播的发送方式,世界上的计算机就可以彼此通信了,问题时世界范围内的互联网是由一个一个彼此隔离的小的局域网组成,那么若果所有的通信都采用以太网的广播方式,那么一台机器发送的包全世界都会收到,太可怕。
上图结论:必须找出一种方法来区分那些计算机属于同一广播域,那些不是。如果是就采用广播的方式发送,如果不是,就采用路由的方式(向不统广播域/子网分发数据包),mac地址无法区分,它只跟厂商有关。
IP协议:
规定网络地址的协议叫IP协议,它定义的地址称为IP地址。
IP地址分成两部分:
网络部份:标识子网
主机部分:标识主机
子网掩码:
所谓子网掩码,就是表示子网特征的一个参数,它在形式上等同于IP地址,也是一个32位二进制数字,它的网络部份全部位1,主机部分全部为0.255.255.255.0
IP协议的作用:一个是为每一台计算机分配IP地址,另一个时确定哪些地址在同一个子网络。
IP数据包:
分为head和打他两部分,无需为IP包定义单独的栏位,直接放入以太网包的data部分。
head:长度为20到60字节
data:最长为65515字节
以太网头 | IP头 | IP数据 |
ARP协议
由来:计算机通信基本靠吼,即广播的方式,所有上层的包到最后都要封装上以太网头,然后通过以太网协议发送,在谈及以太网协议时候,我门了解到通信是基于mac的广播方式实现,计算机在发包时,获取自身的mac是容易的,如何获取目标主机的mac,就需要通过arp协议
功能:广播的方式发送数据包,候去目标主机的mac地址
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。
主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址。
收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。
地址解析协议是建立在网络中各个主机互相信任的基础上的,网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存;由此攻击者就可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗。ARP命令可用于查询本机ARP缓存中IP地址和MAC地址的对应关系、添加或删除静态对应关系等。相关协议有RARP、代理ARP。NDP用于在IPv6中代替地址解析协议。
协议工作方式:每台主机ip都是已知的(我只知道我的局域网ip地址,要给一个非同一网络的我不知道ip地址的电脑发消息,怎么办:NET穿透)
例如:主机172.16.10.10/24访问172.16.10.11/24
一:首先通过ip地址和子网掩码区分出自己所处的子网
场景 | 数据包地址 |
同一子网 | 目标主机mac,目标主机ip |
不同子网 | 网关mac,目标主机ip |
二:分析172.16.10.10/24与172.16.10.11/24处于同一网络(如果不是同一网络,那么下表中目标ip为172.16.10.1,通过arp获取的是网关的mac)
源mac | 目标mac | 源IP | 目标IP | 数据部分 | |
发送端主机 | 发送端mac | FF:FF:FF:FF:FF:FF | 172.16.10.10/24 | 172.16.10.11/24 | 数据 |
三:这个包会以广播的方式在发送端所处的子网内传输,所有主机接收后拆开包,发现目标ip为自己的,就响应,返回自己的mac
④ 传输层
由来:网络层的ip帮我们区分子网,以太网层的mac帮我们找到主机吗,但是只找到主机有用吗,是不是程序之间进行的沟通啊像QQ、浏览器和京东服务器,然后大家使用的都是应用程序,你的电脑上可能同时开启qq,暴风影音,等多个应用程序,那么我们通过ip和mac找到了一台特定的主机,如何标识这台主机上的应用程序,答案就是端口,端口即应用程序与网卡关联的编号。
功能:建立端口到端口的通信(端对端通信)
补充:端口范围0-65535,0-1023为系统占用端口
TCP协议:(TCP把连接作为最基本的对象,每一条TCP连接都有两个端点,这种端点我们叫做套接字(socket),它定义为端口号拼接到IP地址即构成了套接字,例如,若IP地址为192.3.4.16,而端口号为80,那么得到的套接字为192.3.4.16:80
当应用程序希望通过TCP与另一个应用程序通信时,他会发送一个通信请求。这个请求必须被送到一个确切的位置。在双方‘握手’之后,TCP将在两个应用程序之间建立一个双工(full-duplex,双方都可以收发消息)的通信。
这个全双工的通信将占用两个计算机之间的通信线路,只到它被一方或双方关闭为之。
它是可靠传输,TCP数据包没有长度限制,理论上可以无限长,但是为了保证网络的效率,通常TCP数据包的长度不会超过IP数据包的长度,以确保单个TCP数据包不必再分割
以太网头 | IP头 | TCP头 | 数据 |
UDP协议:不可靠传输,‘报头’部分一共有8个字节,总长度不超过65635,正好放进一个IP数据包
以太网头 | IP头 | UDP头 | 数据 |
TCP---传输控制协议,提供的是面向连接、可靠的字节流服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。 UDP---用户数据报协议,是一个简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快 现在Internet上流行的协议是TCP/IP协议,该协议中对低于1024的端口都有确切的定义,他们对应着Internet上一些常见的服务。这些常见的服务可以分为使用TCP端口(面向连接)和使用UDP端口(面向无连接)两种。 说到TCP和UDP,首先要明白“连接”和“无连接”的含义,他们的关系可以用一个形象地比喻来说明,就是打电话和写信。两个人如果要通话,首先要建立连接——即打电话时的拨号,等待响应后——即接听电话后,才能相互传递信息,最后还要断开连接——即挂电话。写信就比较简单了,填写好收信人的地址后将信投入邮筒,收信人就可以收到了。从这个分析可以看出,建立连接可以在需要痛心地双方建立一个传递信息的通道,在发送方发送请求连接信息接收方响应后,由于是在接受方响应后才开始传递信息,而且是在一个通道中传送,因此接受方能比较完整地收到发送方发出的信息,即信息传递的可靠性比较高。但也正因为需要建立连接,使资源开销加大(在建立连接前必须等待接受方响应,传输信息过程中必须确认信息是否传到及断开连接时发出相应的信号等),独占一个通道,在断开连接钱不能建立另一个连接,即两人在通话过程中第三方不能打入电话。而无连接是一开始就发送信息(严格说来,这是没有开始、结束的),只是一次性的传递,是先不需要接受方的响应,因而在一定程度上也无法保证信息传递的可靠性了,就像写信一样,我们只是将信寄出去,却不能保证收信人一定可以收到。 TCP是面向连接的,有比较高的可靠性, 一些要求比较高的服务一般使用这个协议,如FTP、Telnet、SMTP、HTTP、POP3等。 而UDP是面向无连接的,使用这个协议的常见服务有DNS、SNMP、QQ等。对于QQ必须另外说明一下,QQ2003以前是只使用UDP协议的,其服务器使用8000端口,侦听是否有信息传来,客户端使用4000端口,向外发送信息(这也就不难理解在一般的显IP的QQ版本中显示好友的IP地址信息中端口常为4000或其后续端口的原因了),即QQ程序既接受服务又提供服务,在以后的QQ版本中也支持使用TCP协议了。
TCP报文
1 源端口和目的端口,各占2个字节,分别写入源端口和目的端口; 2 序号,占4个字节,TCP连接中传送的字节流中的每个字节都按顺序编号。例如,一段报文的序号字段值是 301 ,而携带的数据共有100字段,显然下一个报文段(如果还有的话)的数据序号应该从401开始; 3 确认号,占4个字节,是期望收到对方下一个报文的第一个数据字节的序号。例如,B收到了A发送过来的报文,其序列号字段是501,而数据长度是200字节,这表明B正确的收到了A发送的到序号700为止的数据。因此,B期望收到A的下一个数据序号是701,于是B在发送给A的确认报文段中把确认号置为701; 4 数据偏移,占4位,它指出TCP报文的数据距离TCP报文段的起始处有多远; 5 保留,占6位,保留今后使用,但目前应都位0; 6 紧急URG,当URG=1,表明紧急指针字段有效。告诉系统此报文段中有紧急数据; 7 确认ACK,仅当ACK=1时,确认号字段才有效。TCP规定,在连接建立后所有报文的传输都必须把ACK置1; 8 推送PSH,当两个应用进程进行交互式通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应,这时候就将PSH=1; 9 复位RST,当RST=1,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立连接; 10 同步SYN,在连接建立时用来同步序号。当SYN=1,ACK=0,表明是连接请求报文,若同意连接,则响应报文中应该使SYN=1,ACK=1; 11 终止FIN,用来释放连接。当FIN=1,表明此报文的发送方的数据已经发送完毕,并且要求释放; 12 窗口,占2字节,指的是通知接收方,发送本报文你需要有多大的空间来接受; 13 检验和,占2字节,校验首部和数据这两部分; 14 紧急指针,占2字节,指出本报文段中的紧急数据的字节数; 15 选项,长度可变,定义一些其他的可选的参数。
TCP三次握手和四次挥手
我们知道网络层,可以实现两个主机之间的通信。但是这并不具体,因为真正进行通信的实体是在主机中的进程,是一个主机中的一个进程与另外一个主机中的一个进程再交换数据。IP协议虽然能把数据报文送到目的主机,但是并没有交付给主机的具体应用进程。而端到端的同您才应该是应用进程之间的通信。
UDP 在传送数据前不需要先建立连接,远地的主机在收到UDP报文后也不需要给出任何确认。虽然UDP不提供可靠交付,但是正是因为这样,省去了很多开销,使得它的速度比较快,比如一些对实时性要求比较高的服务,就常常使用UDP。对应的应用层的协议主要有DNS,TFTP,DHCP,SNMP,NFC等。
TCP,提供面向连接的服务,在传送数据之前必须先建立连接,数据传送完成之后要限制连接。因此TCP是一种可靠的运输服务,但是正因为这样,不可避免地增加了很多开销,比如确认,流量控制等,对应的应用层的协议主要有SMTO,TELNET,HTTP,FTP等
常用的端口号
应用程序 | FTP | TETP | TELNET | SMTP | DNS | HTTP | SSH | MYSQL |
熟知端口 | 2120 | 69 | 23 | 25 | 53 | 80 | 22 | 3306 |
传输层协议 | TCP | UDP | TCP | TCP | UDP | TCP |
1、TCP 服务器进程先创建传输控制块TCB,时刻准备接收客户进程的连接请求,此时服务器就进入了listen(监听)状态; 2、TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这时报文首部中的筒不为SYN=1,同时选择一个初始序列号seq=x,此时,TCP客户端进程进入了SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。 3、TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带序列号,但是同样需要消耗掉一个序号。 4、TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入eatablished(已建立连接)状态。TCP规定。ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。 5、当服务端收到客户端的确认后也进入estableshed状态,此后双方就可以通信了。
一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。
如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
数据传输完毕之后,双方都可释放连接。最开始的时候,客户端和服务端都是处于established状态,然后客户端主动关闭,服务器被动关闭。服务端也可以主动关闭,一个流程。 1、客户端进程发出连接释放报文,并停止发送数据。释放报文数据首部,FIN=1,其序列号为seq=u(等于前面已经传过来的数据的最后一个字节的序号加1),此时客户端进入FIN-WAIT-1(终止等待1)状态。TCP规定,FIN报文段即使不携带数据,也要消耗掉一个序号。 2、服务器收到连接释放保温,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发放了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。 3、客户端收到服务器的确认请求后,此时客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送链接释放报文(在这之前还需要接受服务器发送的最后的数据)。 4、服务器将最后的数据发送完毕之后,就像客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器可能有发送了一些数据,假定此时的序列号weiseq=w,此时服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。 5、客户端收到服务器的裂解释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号seq=u+1,此时客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2**MSL(最长报文段寿命)的时间,当客户端撤销相应的TCB后,才进入CLOSE状态。 6、服务器只要收到了客户端发出的确认,立即进入CLOSE状态。同同样,撤销TCB后,就结束了这次的TCB连接。可以看到,服务器结束TCB连接的时间要比客户端早一些。
MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。 第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。 第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。 为什么建立连接是三次握手,关闭连接确是四次挥手呢? 建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。
三次握手: TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK[1],并最终对对方的 SYN 执行 ACK 确认。这种建立连接的方法可以防止产生错误的连接。[1] TCP三次握手的过程如下: 客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。 服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。 客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。 三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。 四次挥手: 建立一个连接需要三次握手,而终止一个连接要经过四次握手,这是由TCP的半关闭(half-close)造成的。 (1) 某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。 (2) 接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。 注意:FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为,FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。 (3) 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。 (4) 接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。[1] 既然每个方向都需要一个FIN和一个ACK,因此通常需要4个分节。 注意: (1) “通常”是指,某些情况下,步骤1的FIN随数据一起发送,另外,步骤2和步骤3发送的分节都出自执行被动关闭那一端,有可能被合并成一个分节。[2] (2) 在步骤2与步骤3之间,从执行被动关闭一端到执行主动关闭一端流动数据是可能的,这称为“半关闭”(half-close)。 (3) 当一个Unix进程无论自愿地(调用exit或从main函数返回)还是非自愿地(收到一个终止本进程的信号)终止时,所有打开的描述符都被关闭,这也导致仍然打开的任何TCP连接上也发出一个FIN。 无论是客户还是服务器,任何一端都可以执行主动关闭。通常情况是,客户执行主动关闭,但是某些协议,例如,HTTP/1.0却由服务器执行主动关闭。[2] 为什么是四次挥手,是因为TCP建立的是全双工通道,你和我断了,我还是可以给你发消息的,所以你断了之后,也需要我进行断开链接,所以要进行四次挥手确认。
⑤应用层
由来:用户使用的都是应用程序,均工作于应用层,互联网是开发的,大家都可以开发自己的应用程序,数据多种多样,必须规定好数据的组织形式
功能:规定应用程序的数据格式。
例:TCP协议可以为各种各样的程序传递数据,比如Email、WWW、FTP等等。那么,必须有不同协议规定电子邮件、网页、FTP数据的格式,这些应用程序协议就构成了”应用层”。
⑥socket
我们知道两个进程如果需要进行通讯最基本的一个前提是能够唯一的标识一个进程,在本地进程通讯中我们可以使用PID来唯一标识一个进程,但PID直在本地唯一,网路中两个进程PID冲突几率很大。这个时候需要我么另辟蹊径了,我们知道IP层的IP地址可以唯一标识主机,erTCP层协议和端口号可以唯一标识主机的一个进程,这样我们可以利用IP地址+协议+端口号唯一标识网络中的一个进程。
能够唯一标识网络今后曾后,他们就可以利用soaket进行通信了,socket常被翻译成套接字,socket是在应用层和传输层之间的抽象层,它把TCP/IP层复杂的抽象为几个简单的接口供应层调用已实现进程在网络中通信。
Socket又称为套接字,它是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。 在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。当我们使用不同的协议进行通信时就得使用不同的接口,还得处理不同协议的各种细节,这就增加了开发的难度,软件也不易于扩展(就像我们开发一套公司管理系统一样,报账、会议预定、请假等功能不需要单独写系统,而是一个系统上多个功能接口,不需要知道每个功能如何去实现的)。 于是UNIX BSD就发明了socket这种东西,socket屏蔽了各个协议的通信细节,使得程序员无需关注协议本身,直接使用socket提供的接口来进行互联的不同主机间的进程的通信。 这就好比操作系统给我们提供了使用底层硬件功能的系统调用,通过系统调用我们可以方便的使用磁盘(文件操作),使用内存,而无需自己去进行磁盘读写,内存管理。socket其实也是一样的东西,就是提供了tcp/ip协议的抽象,对外提供了一套接口,同过这个接口就可以统一、方便的使用tcp/ip协议的功能了。 其实站在你的角度上看,socket就是一个模块。我们通过调用模块中已经实现的方法建立两个进程之间的连接和通信。也有人将socket说成ip+port,因为ip是用来标识互联网中的一台主机的位置,而port是用来标识这台机器上的一个应用程序。 所以我们只要确立了ip和port就能找到一个应用程序,并且使用socket模块来与之通信。 历史:套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 因此,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通讯。这也被称进程间通讯,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。
基于文件类型的套接字家族
套接字家族的名字:AF_UNIX
unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,可以通过访问同一个文件系统间接完成通信
基于网络类型的套接字家族
套接字家族的名字:AF_INET
(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我们只使用AF_INET)
socket在内的5层通信流程
基于TCP和UDP两个协议下socket的通讯流程
1、TCP和UDP对比
TCP(Transmission Control Protocol)可靠的、面向连接的协议、传输效率低全双工通信(发送缓存&接收缓存),面向字节流。是哟个TCP的引用:web浏览器,文件传输程序
UDP(User Datagram Protocol)不可靠的、无连接的服务、传输效率高,一对一,一对多,多对一,多对多,面向报文(数据包),尽最大努力服务,无阻塞控制。使用UDP的应用:域名系统(DNS),视频流,IP语音(VoIP)。
查看下图比对差异
TCP和UDP下socket差异对比图
一、TCP协议下的socket
基于TCP的socket通讯流程图片:
先从服务器说起,服务器端先初始化socket,然后与端口绑定(bind),对端口进行建通(listen),调用acceptzuse,等待客户端连接。在这时如果有个客户端初始化socket,然后连接服务器(connect),如果连接成功,这时客户端与服务端的连接就建立了。客户端发送请求数据,服务端接收请求并处理请求,然后把回应数据发给客户端,客户端读取数据,最后关闭连接,一次交互结束。
server端
import socket server = socket.socket() server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) ip_port = ('127.0.0.1',8080) server.bind(ip_port) server.listen(3) while 1: conn,addr = server.accept() # 在这里阻塞,等待客户端过来连接 while 1: from_client_msg = conn.recv(1024) # 接收消息,在这里还是阻塞,等待接受消息 print('来自大海的消息:',from_client_msg.decode('utf-8')) if from_client_msg.decode('utf-8') == 'bye': # 如果接收到的消息为bye,退出 break to_client_msg = input('星空:') # 服务端发出消息 conn.send(to_client_msg.encode('utf-8')) conn.close()
client端
TCP_client.py
import socket client = socket.socket() client.connect(('127.0.0.1',8080)) while 1: to_server_msg = input('大海说:') client.send(to_server_msg.encode('utf-8')) if to_server_msg == 'bye': break from_server_msg = client.recv(1024) print('来自星空的消息:',from_server_msg.decode('utf-8'))
上边的代码会有这种情况:第一个连接的客户端可以和服务端收发消息,但是第二个连接的客户端大消息服务端是收不到的,需等到第一个客户端断了之后,才能收到第二个客户端发的消息
原因:
TCP属于长连接,长连接就是一直占用着这个连接,这个连接的端口被占用了,第二个客户端过来连接的时候,他是可以连接的,但是处于一个占线的状态,就只能等着去跟服务器建立连接,除非一个客户端断开之后,然后就可以进行和服务端的通信了。
二、UDP协议下的socket
基于UDP的socket通讯流程
流程:服务器先初始化socket,然后与端口绑定(bind),recvform接收消息,这个消息有两项,消息内容和对方客户端的地址,然后回复消息的时候也要带着你收到的这个客户端地址,发送回去,最后关闭连接,一次交互结束。
简单例子
server端:
import socket udp_server = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1',8090) udp_server.bind(ip_port) from_client_msg,client_addr = udp_server.recvfrom(1024) udp_server.sendto(b'sha',client_addr) print(from_client_msg,client_addr)
client端:
import socket udp_client = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1',8090) udp_client.sendto(b'hello',ip_port) from_server_msg,server_addr = udp_client.recvfrom(1024) print(from_server_msg,server_addr)
简单对话:
server端
udp_server02.py
udp_client02.py
import socket udp_server = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1',8010) udp_server.bind(ip_port) while 1: from_client_msg,client_addr = udp_server.recvfrom(1024) print(from_client_msg.decode('utf-8'),client_addr) to_client_msg = input('服务器说:') udp_server.sendto(to_client_msg.encode('utf-8'),client_addr) udf_server.close()
cilent端:
import socket udp_client = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1',8010) while 1: to_server_msg = input('客户端说:') udp_client.sendto(to_server_msg.encode('utf-8'),ip_port) from_server_msg,server_addr = udp_client.recvfrom(1024) print(from_server_msg.decode('utf-8'),server_addr) udp_client.close()