我们主要关注TCP/IP四层模型,OSI七层模型了解即可
TCP/IP并不是简单指TCP协议和IP协议,而是全称
Transmission Control Protocol/Internet Protocol,中文名是:传输控制协议/因特网互联协议,是指利用IP进行通信时所必须用到的协议群的统称。
TCP通过三次握手建立端对端的连接之后,才能进行通讯,当通讯完成后需要断掉连接。
为什么要进行,三次握手?
为了保证能够正常通讯,逻辑上是应该进行四次握手的,即:
A向B发送同步请求,B回应A收到请求,这表示A传递信息给B是没有问题的。
然后B给A发送同步请求,A回应收到请求,这表示B传递信息给A是没有问题的。
这逻辑上的四次握手,就能保证A和B能够互相通信。
那为什么最后变成了三次握手呢?
为了建立连接,B首先收到A的同步请求后一定会回应A的同步信号并且给A发送同步请求,这就有一个逻辑连贯,所以把B回应A的同步信号和给A发送同步请求合并成一次握手,这就变成了三次握手。
因为需要通过三次握手成功后才能建立连接,所以黑客可以利用这个三次握手的机制来攻击服务端,我们把这种方式成为洪泛攻击。
通过发送大量伪造原IP地址的报文,发送到服务端 ,这样服务端要回应这个伪造的IP地址,因为是伪造的IP地址,肯定完成不了三次握手,这种半开连接就会占用计算机资源,如果大量的出现这种情况,就会导致真实的报文得不到回应。
如何解决洪泛攻击?
无效的连接监控释放、防火墙
为什么握手是三次,挥手却要四次呢?
之前我们分析过,建立连接其实需要的是逻辑上的4次握手,只有通过这四次才能确保双方互相通信的通畅,同理,断开连接的时候也需要双方都向对方提出断开的申请,并且双方也需要回复,所以也是4次。
握手三次是因为,在逻辑上的四次中,第二次和第三次握手的逻辑是连贯的,所以可以合并成一次。
因为TCP连接是端对端全双工的,即两端都可以进行发信息和收信息,当想断开连接的时候,需要双方都向对方提出断开的申请,并且双方也需要回复,所以是4次挥手
为什么挥手的第二次和第三次握手不能合并?
因为不是一方申请断开连接时,另一方也想立刻断开连接,所以会出现第二次和第三次有个时间差,这个时间差导致不能合并,所以挥手在理论上是四次,但是如果我们抓包看的话,会出现挥手三次的情况,因为大多数情况下,第二次和第三次是同时的,在实际中就给合并了,这就是理论和现实的差距,理论和刻板,现实很灵活。
为什么需要TIME_WAITING状态?
MSL是最长报文段寿命,即一个IP报文数据在网络上存活的最长时间,在RFC的文档中定义为2分钟,超过两分钟就会被网络所丢弃,现实中没有这么长的时间,一般是30秒。
1.当服务端发送断开连接请求时,有可能丢包,丢包需要服务端重传,可能出现要客户端等待的情况,所以不能立刻从FIN_WAIT_2状态到CLOSED状态,需要这个TIME_WAITING状态
2.当连接处于TIME_WAITING状态的时候是不允许释放端口的,当服务端还有数据想传过来,有TIME_WAITING的等待,不会出现数据传输到下一个获取这个端口的错误。
TCP将每个数据包都进行了编号,这就是序列号。
序列号的作用:
a、保证可靠性(当接收到的数据总少了某个序号的数据时,能马上知道)
b、保证数据的按序到达
c、提高效率,可实现多次发送,一次确认
d、去除重复数据
数据传输过程中的确认应答处理、重发控制以及重复控制等功能都可以通过序列号来实现
TCP通过确认应答机制实现可靠的数据传输。在TCP的首部中有一个标志位——ACK,此标志位表示确认号是否有效。接收方对于按序到达的数据会进行确认,当标志位ACK=1时确认首部的确认字段有效。进行确认时,确认字段值表示这个值之前的数据都已经按序到达了。而发送方如果收到了已发送的数据的确认报文,则继续传输下一部分数据;而如果等待了一定时间还没有收到确认报文就会启动重传机制。每一个报文都需要对端做确认应答
当报文发出后在一定的时间内未收到接收方的确认,发送方就会进行重传(通常是在发出报文段后设定一个闹钟,到点了还没有收到应答则进行重传)。
一种情况是发送包丢失了
这种情况很简单,发送包丢失时,如果一段时间没有收到确认包,则重新发送这个包。
另一种情况是回应包ACK丢失了
当回应包ACK丢失时,因为一段时间没有收到确认包ACK,,则重新发送这个包,因为是ACK丢失,表明接收端已经接收了那个包,这次接收端接收到重复的包就会丢弃掉,并且重发回应的包。
每一个报文都有其序列号,超时重传和应答确认都是靠序列号来控制的
重传时间的确定:
重传时间的确定:报文段发出到收到应答中间有一个报文段的往返时间RTT,显然超时重传时间RTO会略大于这个RTT,TCP会根据网络情况动态的计算RTT,即RTO是不断变化的。在Linux中,超时以500ms为单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。其规律为:如果重发一次仍得不到应答,就等待2500ms后再进行重传,如果仍然得不到应答就等待4500ms后重传,依次类推,以指数形式递增,重传次数累计到一定次数后,TCP认为网络或对端主机出现异常,就会强行关闭连接。
一段报文可能分包发送,所以需要序列号,因为每个数据包都有自己的序列号,这样就可以给数据进行排序
接收端处理数据的速度是有限的,如果发送方发送数据的速度过快,导致接收端的缓冲区满,而发送方继续发送,就会造成丢包,继而引起丢包重传等一系列连锁反应。
因此TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制叫做流量控制。tcp通过滑动窗口来进行流量控制
如果主机A是我们的发送方,他在发送数据的时候需要维护一个窗口,接受窗口就是告诉发送方,接收方还有多少的缓存空间,tcp是全双工通信,所以说通信的任何一方都维护着另一方的一个接收窗口
接受窗口(表示表示接收方当前可用的缓存空间)
接受窗口表示接收方还能有多大的缓存空间
因为这些数据是会动态变化的,我们这个接受窗口也是动态变化的,所以我们称这个窗口为滑动窗口那发送方是怎么拿到接收端的滑动窗口大小的数据呢?
tcp是全双工通信,这个时候我们的接收方可以再发送一个报文告诉发送方,在tcp报头中,有一个位置是关于窗口大小的
TCP的两端都可以进行收发报文。
为了避免由于网络拥堵而采取的对发送方发送速率的限制称为拥塞控制
TCP 通过拥塞窗口实现拥塞避免。
每个 TCP 连接的发送方都会去感知网络的拥塞程度,然后去进行拥塞控制,那么 TCP 的发送方是如何感知到当前这个网络存在着拥塞呢,丢包,只要出现了超时就极有可能出现了网络拥堵。那 假设现在出现了网络拥塞,那么 TCP 如何限制传输的速率呢?TCP 的每一端除了维护进行流量控制的滑动窗口外,还会维护一个拥塞窗口(cwnd),拥塞窗口就是对 TCP 发送方的发送速率进行限制的,具体来说的就是 TCP 会控制发送方发送到连接中的但是还没有被接收方确认的数据量。
那我们改变拥塞窗口的大小,就可以调节发送方发送数据的速率。那么发送的速率是多少呢?首先用 rtt 表示一次通信往返所用的时间,那么速率就等于 cwnd/rtt。一般来说 rtt 都是比较固定的,所以调整 cwnd 的值就可以调整发送速率。那我们应该如何确定当前发送速率是多少才合适呢?那就要依靠 TCP 的拥塞控制算法了。拥塞控制算法的实质就是如何来调整 cwnd 的大小。一说到大小就得有衡量单位,那窗口的衡量单位是 mss 最大的传输单元。那我们知道 TCP 分为 TCP 首部和数据两部分,mss 就是去控制数据字段的大小的,那这个值呢是需要通讯双方进行约定的。比如说一般的值呢是一千四百六十个字节。首先发送方发送数据的原则是什么呢,只要网络不堵,我就尽可能多的去发,网络赌的话,我就减小这个窗口的大小。
TCP拥塞控制流程:
TCP拥塞算法共有4种:慢开始、拥塞避免、快重传、快恢复
慢开始
慢开始发生在最开始,这个时候不断试探网络是否把握的住,拥塞窗口(cwnd)以n²的增速开始增长,然后到了设置的阈值,我们就采取拥塞避免的算法每次加一的试探网络,当然后面肯定避免不了超时,我们这时候阈值设为当前阈值的一半,我们重新开始慢开始,到达现在的阈值开始拥塞避免。
拥塞避免
每个传输轮次,拥塞窗口cwnd只能线性加一,而不是像慢开始算法时,每个传输轮次,拥塞窗口cwnd按指数增长。
快速重传
接收器接收到一个不按顺序的数据段,接收器会立马给发送器发送重复确认,如果发送机接收到三个重复确认,它会假定确认件支出的数据段丢失了。这样就不会造成发送方对后面报文出发超时重传,而是提早收到了重传。然后开始快恢复算法。
快恢复算法
发送方一旦收到3个重复确认,就知道现在只是丢失了个别的报文段。于是不启动慢开始算法,而执行快恢复算法;
1.发送方将慢开始门限ssthresh值和拥塞窗口cwnd值调整为当前窗口的一半;开始执行拥塞避免算法。
2.也有的快恢复实现是把快恢复开始时的拥塞窗口cwnd值再增大一些,即等于新的ssthresh + 3。
既然发送方收到3个重复的确认,就表明有3个数据报文段已经离开了网络;
这3个报文段不再消耗网络资源而是停留在接收方的接收缓存中;
可见现在网络中不是堆积了报文段而是减少了3个报文段。因此可以适当把拥塞窗口犷大些。