从大学就开始接触到了网络协议,零零散散不成体系,那时也没有理解的多么透彻,更别谈将它应用到实际。工作开始渐渐的意识到网络基础理论的重要性。写博客的用意如下,整理自己的知识,查漏补缺,检查自己还有哪些没有理解的,毕竟基础知识决定了以后在技术方面能走多远;再者就是要能帮到了后来者再好不过了。自己知识有限,还望有缘人指正一二,万分感谢。
前言:
本篇文章主要讲述的是,七层协议中的物理层到传输层协议,对于应用层协议中DNS和HTTP会单独的作为一个模块阐述,另外网络协议精妙复杂,绝不是这一篇文章可以描述清楚的,文章难免会出现不是十分严谨或是不太详细的,先建立个宏观体系,再谈些重要的细节。说明下TCP/IP协议簇不单只是TCP和IP协议。
兵马未动粮草先行,直接上图
先用大白话说下OSI参考模型。
1、为什么要分模块?
这就好比一个公司,会有很多部门,每个部门可以理解为只做一个事情,一个部门可能在为另一个部门提供服务,也可能别的部门在服务它。争取每个部门只做一件事,就像一个函数只做一件事一样。作为互联网最基础的网络,怎么能全部在一起解析了,还是得分模块,这样才是一个老司机该做的事。不过我觉得这种模块的划分还是面向了具体,而非抽象。
2、OSI完成的是什么任务?
当然是通信任务啦,废话我也知道,能不能具体些。举个简单的例子,小王在地址栏输入www.baidu.com按下了回车键,这一次点击发生了哪些内容。www.baidu.com?这是什么鬼,我怎么知道这是谁,他在哪了。显然我们首先是找到这个地址在哪里吧,这样我们才能传输一些信息吧。
第一步:DNS域名解析服务器,要想使用www.baidu.com得先注册才成,不是你输入什么都可以的。先不说详细了,就知道有个DNS服务器,他就是保存键值对信息,如www.baidu.com对应了115.239.210.27这个地址。这个叫做IP号,它的作用就是定位,(就像你的家庭地址加上你的名字一样,MAC地址像身份证号码)。
第二步:知道你想要干什么。就是复杂的协议分装了,先进行HTTP封装,比如你的请求方式(GET),URL是什么(www.baidu.com),用的什么协议(HTTP1.1),请求的整个长度是多少。这些都知道了后,百度服务器就知道你要干什么了,因为协议有自己的格式,也可以根据这些条件解析出来了。
第三步:将你的请求安全的送达到目的地的哪一个服务器处理。www.baidu.com默认是80端口,操作系统会根据端口的不同,将不同的数据给相应的进程处理。浏览器的端口假设为53141.有了目标端口和本地端口,就可以知道目标进程和目标服务器也能找到自己的进程了。这时候传输层封装完毕,到达了网络层。网络层会将自己的IP和目标的IP写入。这样有了IP和端口就能找到设备中的进程了。为什么有了IP地址就能找到目标设备了,这么神奇。这时候网关就派上用场了,网关多是路由器的IP地址,它会根据子网掩码判断你是不是本地的。不是本地的就必须从网关出发,这是到外网的必经之路。你的设备通过ARP协议广播192.168.1.1这个网关的MAC地址是多少?知道了MAC地址后,开始封装数据链路层,将你的MAC地址和网关的MAC地址写入。根据数据链路层判断下一个数据包是给哪个设备,而网络层的IP是最终的目标IP。每走一跳,数据链路层的目标和源MAC地址都会变。然后到达了物理层,它解决的是与硬件的关系,如大于多少伏的电压代表1,小于多少代表0,因为本质上电脑只识别0和1。再如,模拟信号和电信号的转换。这样就一步一步的到达了目标百度服务器,一步一步从物理层反过来解析,最后将消息转给的监听80端口的进程处理。一次简单的过程就这样了,百度服务器终于收到了我们的一次请求了。
问题:集线器、交换器、路由器大体是怎么工作的?
- 1、集线器,主要功能是对接收到的信号进行再生整形放大,以扩大网络的传输距离。收到了一位bit就进行转发,不解析不处理。
- 2、交换器,收到字节流后,解析出数据帧,并查看目标的MAC地址,判断出从哪个交换机口进行转发出去。它是二层设备。
- 3、路由器,不仅会解析出MAC地址还会解析出目标的IP,检查是否丢弃还是转发给下一跳哪个设备。它是三层设备。
一、网络层
1、IP地址
众所周知,Windows系统查询网络IP地址为ipconfig,Linux中为ifconfig或者ip addr命令。Windows如下图所示。
IPv4的IP地址是32个字节的,如百度的115.239.210.27就是一个IP地址,它的作用是一个网卡的地址,具有定位作用。现在想一想MAC地址是一个网卡出厂就具备的全球唯一的地址,那么有了MAC地址后,怎么还需要IP地址了?答案就是没有IP地址根本定位不了,给你一个百度的服务器MAC地址,你怎么能找到他了。MAC地址就像我们的身份证,IP地址就如同我们的家庭住址+名字。比如给你小王的MAC地址,你也不可能找到他,只有先通过他的家庭住址和名字,才能找到他。所以说MAC地址不具备大范围的定位作用,只有在局域网内才有作用,这就是MAC地址和IP地址的一个区别。
32位的IP地址被分成了一下五类,又大大的减少了IP地址数量。A、B、C是有网络号和主机号组成的。这样是为了区别是不是在同一个局域网内,网络号代表的是小区,主机号代表的是哪一号房间。这样不同的小区就可以都有1001号房间了,但不会产生冲突,因为他们的网络号不同。
如下图所示,A、B、C三类的最大主机数量,很容易产生浪费。私密地址代表什么了,我们上学的时候IP都是172.16开头的,貌似很多大学的IP都是一样的,你会问这不是产生冲突了吗,只能说,这些IP在局域网里面是正常使用的,一段到了公网后,这个就会被替换成一个不冲突的IP了,数据请求返回时,再被替换回来,这样就保证了不冲突,详情下面会说,现在有个概念就可以了。
怎么判断是否是同一个局域网的IP地址了?
通过配置的子网掩码。如下图是一个C类的私有IP地址,网络号为24位,主机号位8位,广播地址为192.168.1.255,一般默认的网关为192.168.1.1.将子网掩码和IP地址按位与计算后,就可以得到网络号了,也就可以判断目标IP是否是要出网关了。
D类地址是组播地址,也就是说这个组的网卡都会收到改组的数据。
此外还介绍一个特殊的IP地址,127.0.0.1。他是个环回接口,这个地址用于本机通信,经过内核处理后直接返回给本机。
Linux中配置IP地址如下:
sudo ifconfig eth1 192.168.1.174/24 //给eth1这个网卡配置IP和子网掩码
sudo ifconfig eth1 up // 启动
简单的数据发送过程:系统会判断数据包的目标IP是不是在同一个网段中,如果是是同一个网段,他会通过ARP协议广播获取目标IP的MAC地址,直接发送给目标即可。如果是跨网段,那么获取网关的MAC地址,把数据发给网关就不管了。
2、DHCP协议(动态路由协议)
日常生活中,我们都是插上网线就可以用了,并没有配置IP啊。那么这个过程就会使用到了DHCP协议,由DHCP服务器管理了IP的分配,并分给刚来的网卡一个可用的IP。
简单说DHCP就是负责管理IP地址的,简单。不过我所在的公司为了可控都是采用静态IP的。需要管理员分配IP并配置。
DHCP工作工程:
想想一个刚来的电脑怎么才能和DHCP服务器联系了,毕竟它什么也不知道,这时候广播地址就派上用场了。新的电脑就会使用0.0.0.0这个IP地址,目的IP为255.255.255.255.源端口为68,目标端口为67,发送一个UDP的广播。这样DHCP服务器收到了,就知道新来了一个电脑需要IP,服务器就选择一个IP,也是通过广播的方式发送IP、子网掩码、网关等相关信息。这样新的电脑会收到了一个IP地址,但是如果要是多个DHCP发送了多个IP了?新的电脑会选择一个IP,继续发送广播包,告诉DHCP服务器,自己所选用的IP号和一些其他信息,当然DHCP服务器收到了广播后,会返回给新电脑一个ACK确认包,这样一次完整的DHCP过程才算结束。
DHCP服务器会不仅可以动态分配IP,还可以回收IP,正所谓有借有还再借不难嘛,DHCP服务器会在租期时间结束的时候自动的回收IP该IP。但如果网卡的IP还要用该怎么办了?客户端租期时间过去的时候就重新向服务器发送请求,客户端收到服务器的返回后,就会更新新的租赁参数。
3、从物理层到数据链路层
开始我们就说了,物理层解决的是,如何在传输媒体上传输比特流,而不是指具体的媒体,如双绞线、无线等,抽象的作用。通过调制解调器将电信号和模拟信号进行转化等等。物理层完成的是对硬件层的封装。
此外物理层还需要对数据帧再次封装,加一个起始头,不然怎么知道这是不是一个数据帧了。
接下来是数据链路层:
先给抛几个问题:
- 1、数据包是谁都可以接收吗?
- 2、发送的时候有错误该怎么办?
- 3、解析的时候怎么正确的解析,而不导致错误,如ARP协议和IP协议格式肯定不一样。
- 4、发送的时候会不会有顺序的问题了?
为了解决上面几个问题,先给出数据帧的封装格式:
第一个问题:数据包当然不是谁都可以接收的,但都在一个局域网里面,你发送的数据肯定都能收的到,只不过不是目标网卡自动过滤了消息罢了。只有数据帧的目标MAC和自身网卡的MAC地址相匹配才可以接收。当然这本身就是个漏洞,自己捯饬捯饬不是自己MAC的数据帧也能收到,所以在网上传输的数据本身就是不安全的。
第二个问题:为了保证数据的完整值,总得有个标志对吧。因为在网上传输的过程中很有可能出现错误的情况。当封装成帧发送的时候,会将数据通过算法生成一个CRC检验值。这样下一跳收到的时候,也会生成该数据的CRC。如果两者的CRC校验值是相等的,那么就认为是完整的,才会走下列流程。反之,丢弃不管了。
第三个问题:通过两字节的类型就可以判断此时传输的是什么协议,通过标志来代表是什么业务。笔者在制定公司的通讯的协议时,也是通过和服务端协商将不同的标志代表不同的业务。如果是IP数据就用IP格式的方式解析即可。
第四个问题:
当在局域网发送数据帧的时候,先侦听信道是否空闲 ,若空闲,则立即发送数据。若信道忙碌,则等待一段时间至信道中的信息传输结束后再发送数据;若在上一段信息发送结束后,同时有两个或两个以上的节点都提出发送请求,则判定为冲突。若侦听到冲突,则立即停止发送数据,等待一段随机时间,再重新尝试。这就是CSMA/CD协议,由于冲突的认定的时间为2T,小于2T的时间内又回来了,这说明信道空闲则发送。所以数据帧的最小大小要为64byte,而且数据线还不能大于100米,否则会造成认定时间错误。
当出了局域网后,进入了公网。不管三七二十一,有数据包出来就发送。这样造成了数据冲突怎么办,他就不管了,反正他也管不了,没法知道数据已经冲突了,这就交给传输层解决。反正数据链路层我就是尽量的发送。
此外还可以通过划分信道的方式。如ADSL技术,早期的时候用电话线边打电话边上网。ADSL技术采用频分复用技术把普通的电话线分成了电话、上行和下行三个相对独立的信道,即电话和上网发送数据的频率不一致。从而避免了相互之间的干扰。用户可以边打电话边上网,不用担心上网速率和通话质量下降的情况。
工作在数据链路层的设备是交换机。接下来说明下交换机和集线器的区别:
集线器很简单,当有数据包经过他的时候,什么也不管不判断,直接进行广播转发了。
相比较集线器,交换机就智能多了,他增加了判断功能。如下图,机器1发送一个ARP广播寻找机器2的MAC地址的时候。当2收到了之后,他会直接响应,当交换机A也能收到,他也会进行发送广播给右边的局域网,但是交换机A会发现机器2的MAC地址不是在右边。所以当机器1再次通过ARP寻找机器2MAC地址的时候,交换机A就不会再转发到右边的局域网中了,因为它可以记住。若是换成Hub(集线器),它从不解析包,直接转发。
但是这么好用的交换机也会带来新的问题,如果交换器成一个环的时候,那么就会出现无限循环-复制-再循环的问题,最终会塞满整个网络。解决办法就是将一个环通过算法解析成一棵树的形式,这就是STP协议。详细内容我也不太懂,感觉意义不太,以后有空再研究了。
4、ICMP协议(互联网控制报文协议)
首先为什么未出现这个协议了?ICMP协议是在网络层中,它是在IP协议的上面,说明IP协议是为ICMP协议服务的。因为网络世界错综复杂,当一个数据包在网络传输不能到达的时候,你得知道是怎么回事吧,是生命周期都用完了都找不到,还是终点不可到达了。作为一个成熟的网络协议,必须要心里有数。有了问题我就给你发个ICMP包,这样你就知道当前是什么情况了。
通过TYPE和CODE就知道当前是问题了,下面是从百度百科中截取的部分对照表。
ICMP的一个方式就是差错报文类型,另一个是查询报文类型ping命令。
从TYPE角度来看,终点不可达为3,源主机抑制为4(目标主动停止),超时为11(生命周期SST用完了)。这样就知道当前怎么回事了。CODE是更加详细的问题描述,0代表网络不可达,1代表主机不可达等等。
ping命令
在公司,每次连不上服务器,运维大佬都会先说下,先ping一下,检查网络之间是不是通的。当然这个也不是十分准确的,有的时候服务器会过滤掉ICMP协议的内容,最好改用Telnet。
这个ping命令发出去的包是符合ICMP协议的。这个是主动查询报文类型,如上图的ICMP报文格式中,ping的类型多了标识符,序号和数据。其中标识符代表不同的任务,序号代表为了这个任务发送了多个数据包,总得给不同的数据包标个序号吧,这样就会知道谁回来啦,谁没回来。
比如ping 192.168.1.2(位于笔者电脑同一个局域网中)
开始执行的时候,主机会构建一个ICMP包,TYPE为8,CODE为0。这样就代表ping请求了。并分配一个标识符,和顺序号,每发一个数据包,顺序号都会自动加一。有了顺序号就会就算往返时间了,在一定时间没返回,就会被认为是不可到达。ICMP数据包就会到达IP层,封装层IP数据包。当然也会用到192.168.1.2、ARP获取目标MAC地址等等。这样目标收到后,开始解析,对比是不是自己的。数据链路层检查后,交给IP层,最后再到了ICMP层。ICMP会分析传递的内容,并构建一个响应的ICMP,TYPE=0,CODE=0,顺序号一致,返回回去。这样一个简单的ping操作就完成了。
ICMP差错报文类型的使用
Windows中使用tracert ip命令,就可以查看每一跳的IP地址了,这就是利用了ICMP协议,通过设置TTL值。当TTL=1的时候,那么经过了第一个网卡后就挂了,会返回一个带有当前IP的ICMP数据包。再设置TTL=2,这样就拿到了第一个网卡的IP地址。通过欺骗的方式还有很多,通过设置数据包不分片来获取沿途的MTU大小。当然还有其它的应用了。
5、IP协议
一台电脑怎么上网?先配置网卡,IP地址、子网掩码和默认网关。DHCP可以默认配置的。网关是很重要的,没有网关,你的电脑根本到不了其他的网段,因为网关是到达英特网的下一跳。
IP是面向点对点的,通俗的说就是找到该网卡的设备。如上图所示,先说明每个字段的基本含义再说。
- 版本 : IP版本,IPV4(32位) 、IPV6(128位)
- 首部长度:头部长度
- TOS:设置优先级、吞吐量、延迟信息
- 总长度: 首部和数据之和的长度
- 标识:IP软件在存储器中维持一个计数器,每产生一个数据报,计数器就加1,并将此值赋给标识字段。当数据报由于长度超过网络的MTU而必须分片时,这个标识字段的值就被复制到所有的数据报的标识字段中。相同的标识字段的值使分片后的各数据报片最后能正确地重装成为原来的数据报。
- 标志:前只有2位有意义。MF=1即表示后面“还有分片”的数据报。MF=0表示这已是若干数据报片中的最后一个。只有当DF=0时才允许分片。
- 片偏移:较长的分组在分片后,某片在原分组中的相对位置。
- 生存时间:每到一个路由器,就需要减一,到0时候停止发送。
- 协议:协议字段指出此数据报携带的数据是使用何种协议,TCP/UDP/ICMP/IGMP,以便使目的主机的IP层知道应将数据部分上交给哪个处理过程。
- 首部校验和:路由器都要重新计算一下首部检验和
- 最主要的是目标IP和源IP地址(代表了面向点对点)
你的电脑访问另外一台电脑可以分为两种情况,一是同网段的访问,另一种便是不同网段的访问。
公共点:都先要通过子网掩码判断是不是同一个网段,若是同一个网段就不关网关什么事了。
如果判断是不同网段,那就开始分装传输层、IP协议头、将自己和网关的MAC地址分装起来,开始发送。网关会开始解析出目标MAC地址,发现是自己的。然后在解析出IP头,判断这个数据包要到那里去。这里可以通过静态路由表或者动态路由来查询下一跳是谁。然后将解析出的数据包开始一层层的分装。只不过这时候的源MAC地址是网关的,目标MAC地址改成了下一跳的MAC地址了。所以说,每经过一跳MAC地址都会改变。
从网关的角度划分,可以分为转发网关和NAT网关。
为什么会出现NAT网关了?这是因为私有IP的出现,比如你学校上网的IP是192.168.1.101,合工大的也有一个IP叫做192.168.1.101。这个时候你去访问他,你要是直接进行访问,那是不可能的,你的电脑直接就会判断这是访问我自己的。所以这个时候要进行转换IP,NAT网关就是这样作用的。
现在就以NAT网关为例,探讨A与B通信过程:
显然服务器A和B的地址是一样的,但是这个地址仅限于局域网中,首先服务器B有一个国际的IP,假设是192.168.56.2。网关B上有一个记录,192.168.56.2对应了局域网中的192.168.1.101这个地址。
这个时候A开始发送数据包了:
源IP为192.168.1.101,目标IP为192.168.56.2,目标MAC为网关A的。
网关A收到了数据包后,开始解析。找到下一跳,并发送给了192.168.56.2,此时A也要有个国际的身份192.168.56.1,那么发送包的内容是:
源IP为192.168.56.1,目标IP为192.168.56.2,目标MAC为192.168.56.2的。
数据包到达了192.168.56.2这个口后,因为路由器B是一个NAT网关,开始将192.168.56.2这个地址转换成192.168.1.101,于是改成访问了192.168.1.101这个网卡了。经过这样的过程就达到了替换的过程了。当然了真实的替换是比较复杂的,都会有相应的算法记录,绝不是简简单单的通过IP地址来的,这里就一带而过了。
通过访问https://www.whatismyip.com就可以访问到自己公共的IP地址了。
IP路由协议:
接下来说说IP路由协议,网络层的一个很重要的作用就是提供IP选址的服务。路由协议分为静态路由协议和动态路由协议。
静态路由协议:
配置静态路由,就是给一个网卡设置一个路由规则,一个简单的路由规则包括目标IP、从哪个口出去、下一跳的网关。
Windows中静态路由操作:
route add 10.253.251.0 mask 255.255.255.0 -p 192.254.1.1 //添加一条静态路由
route add 10.253.251.0 mask 255.255.255.0 -p 192.254.1.1 // 删除
静态路由一般用于网络的拓扑简单的情况下。复杂的网络下,会牵一发动全身,复杂会指数的增加。
动态路由协议:
如果能够动态的根据网络的实际情况生成路由表,那就太好了,别怕,动态路由算法拯救你。归根结底,网络就是一张复杂的图,动态路由协议就是找一个最小路径。大学的数据结构中,有两种策略,一种是深度遍历,另一个是广度遍历。
第一大类算法是基于BellmanFork算法的距离矢量路由。基本思路是:每个路由器都会保存一个全局的路由表,每条数据就是目标IP和到达目标IP的距离。每隔一段时间,每个路由器就将自己的路由表情况告诉邻居,每个路由表在对照自己的路由表,进行更新操作。
缺点就是:每次发送全局的路由表,极度的冗余;对于一个路由器挂掉了这样的消息就有问题了,别的路由器会一直的从邻居那里获取到达坏掉的路由器的距离,这样一直一直增长超过最大值,才会认为这个路由器断掉了。
第二类算法是基于Dijkstra算法的链路状态路由算法。他的基本思路就是,一个路由启动的时候,他会给邻居发一个消息,邻居在回复,时间除以二就是距离了。再将这个路由广播出去,这样整个网络就知道了。每个路由器就有了一张图,再用路由表进行Dijkstra算法找到最短路径。
6、UDP协议(传输层):
先回顾下,网络层完成的是找到目标设备,但是找到了目标设备还远远的不够,因为一个设备有很多进程。所以传输层的任务就是找到目标地址的目标端口。
简单的说下,UPD和TCP的区别:1、TCP是面向连接的,UDP是无连接的。所谓的建立连接,是指客户端和服务端通过三次握手,建立一个双方的数据结构,这样就知道对方处于什么状态下了,就这叫做面向连接的。2、TCP的面向连接,可以做到可靠性的数据传输,UDP则是不安全的。3、TCP是面向字节流的,这意味着接受者接收的时候接收的一个流,而UDP继承了IP包特性,发和收都是一个个包。4、TCP是通过拥塞窗口可以做到拥塞控制。
从UDP协议头就可以看出UDP相当简单,源目标端口号、长度、校验值和数据外就没了。
因为简单,在已下的场景用的比较多:
- 内网情况,网络比较好。
- 对丢包不太敏感的,如直播
- 广播主播的应用,不是一对一建立连接的。
虽然UDP比较简单,但应用比较多,很多是基于UDP协议进行的二次封装,这样既保证了可靠性,也具备了速度。如谷歌提出的QUIC应用层协议,可以快速的建立连接、减少重传时延、自适应拥塞控制等等;
7、TCP协议
摘自百度百科,看戏每个字段的含义:
- Source Port是源端口,16位。
- Destination Port是目的端口,16位。
- Sequence Number是发送数据包中的第一个字节的序列号,32位。
- Acknowledgment Number是确认序列号,32位。
- Data Offset是数据偏移,4位,该字段的值是TCP首部(包括选项)长度除以4。
- 标志位: 6位,URG表示Urgent Pointer字段有意义:
- ACK表示Acknowledgment Number字段有意义
- PSH表示Push功能,RST表示复位TCP连接
- SYN表示SYN报文(在建立TCP连接的时候使用)
- FIN表示没有数据需要发送了(在关闭TCP连接的时候使用)
- Window表示接收缓冲区的空闲空间,16位,用来告诉TCP连接对端自己能够接收的最大数据长度。由此做到流量控制。
- Checksum是校验和,16位。
- Urgent Pointers是紧急指针,16位,只有URG标志位被设置时该字段才有意义,表示紧急数据相对序列号(Sequence Number字段的值)的偏移。
TCP三次握手
- 开始都是CLOSED状态,A发送一个SYN=1,代表开始同步请求,seq=x代表数据包第一个字节的序列号。A由此进入到SYN-SENT等待连接状态。
- B收到A请求连接后,由LISTEN监听状态到达SYS-RCVD状态。回复数据包括,SYN=1代表我也是请求连接,seq=y代表我的开始字节号是y。ACK=1代表收到了你的请求,ack=x+1代表是对你的序号为x的确定。
- A收到了B的响应后就进入到了连接状态了,那么对于A来说已经处于连接状态,B还不是,所以A还要个B发一个响应。ACK=1 ack=y+1代表对序列号为y的确认。B收到后,才算三次握手结束。
面试的时候总是问,为什么要三次握手了,两次行不行?三次握手是个折中办法,并不是非常可靠,100次握手也不可靠,但肯定不能无限的握手吧,所以就三次了。两次不行的原因是,A来说一次响应一次回复收到,代表A连接成功,那么B却是只发了一个请求,并没与响应,对B来说就一点也不可靠了。所以得B也收到了响应才算握手成功。只要双方的消息都有来有回就可以了。
三次握手的作用处理建立连接之外,还是双方确定对方数据包的开始位置即序号的起始。这样才可以为为以后收发数据做好准备了。
TCP四次挥手
为什么挥手要四次,握手三次就可以了?因为A数据传输结束后想结束握手,但不确定B的数据就一定传输完成了啊,只有B的数据传输完成后才会发送传输结束请求。
- 开始A发送FIN=1代表想结束这次会话开始进入到FIN-WINT-1状态
- B收到了,响应A刚才的请求,代表我同意你的结束请求,但此时并不是真正的断开连接。
- 等到B数据传输完成后,也发一个断开连接请求,FIN=1,ACK=1,同时也是对上一次响应的回复。
- A收到了断开连接请求并没有马上进入到CLOSED状态,这是防止发给B的响应B并没有收到,只有需要等待2MSL周期才认为结束,同时B收到了A的响应消息就进入到了CLOSED状态。A在超过2MSL外又收到了B的断开连接请求后,会发送一个RST=1的响应,告诉B我早就断开连接了。
滑动窗口机制
首先滑动窗口机制解决了数据包的顺序问题、丢包问题和流量控制。它是发送方的一个机制,记录了当前发送方的数据包发送情况,哪些发送了,哪些确认了,哪些需要重发等等。如图所示:
- 1-3 代表了服务端响应已经收到了,这时客户端就可以将其从缓存中去掉
- 4-9 代表了客户端已经发送了,但还没得到确认,至于服务端收没收到不确定
- 10-12 代表了还没发送却可以发送,因为当前网络是可以忙的过来的
- 13-15 代表了不仅没发送,这会还不能发送,要不然会让网络拥塞
- 1-5代表我也经接收了,并且已经确认过的
- 6-14代表还没接收到,这是接收端还能接收到的最大数量了
- 15代表,不能接收的,接收了就处理不过来了
此时接收端的滑动窗口大小为:等待接收未确认的这部分,接收端会将这个值一同的返回给发送端,和发送端一起调节流量发送速度。
顺序问题和丢包问题
假设8和9接收端已经收到了。但是这时还不能接收,因为6/7还没有来,这就出现了顺序问题。假设4-7全部丢失了,那么接收端该怎么处理了,其实接收端会有个计时器,如果超过一定的时间(时间是根据网络情况自动的调节的),就默认丢了,就会重新的发送。
流量问题
流量是针对接收方来说的,如果接收方处理不过来,就会响应时一并发送窗口大小,如果窗口不断的变小,那么接收端也会调节大小。这样就会使接收方发送的数据减少。
拥塞窗口机制
拥塞窗口是为了解决网络拥塞的问题,滑动窗口则是解决接收端缓存过大问题。
拥塞窗口采用的慢开始、拥塞控制、快重传、快恢复的方法。
发送端建立一个拥塞窗口,该窗口大小使用拥塞窗口和滑动窗口一并控制的。发送端先发送一个1字节的试探报文,这叫做慢开始。当收到第一个字节的数据的确认后,再发送2个字节的报文;依次以2次方数量发送,发送到什么时候为止了,这就开始设置一个阈值。小于它就指数增长,大于的时候就改用线性增长,每次加一个字节。当出现丢包的时候,就将发送值改成1字节,再将慢开始门限设为原先的一半,重新的走遍开始的流程。
当接收端发现中间丢失了一个数据包的时候,发送三个前一个数据包的确认包,于是发送端就是快速重传,这就是快重传。将起点设置为之前的一半,这样就不用从1个数据包开始发了。但是之后就改成了线性增长了。