TCP总结
Last updated
Was this helpful?
Last updated
Was this helpful?
TCP协议通过使用连续ARQ协议和滑动窗口协议,来保证数据传输的正确性,从而提供可靠的传输。 TCP 的可靠连接是靠 seq( sequence numbers 序列号)来达成的。
ARQ协议,即自动重传请求(Automatic Repeat-reQuest),是OSI模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧,它通常会重新发送。
停止等待ARQ协议:处于发送一个分组、等待确认、接收确认后再发送一个分组的流程。如果流程中出现出现差错(如接收到分组检测时差错,或者传输过程丢失分组),接收方不会发送任何消息。它的可靠性通过超时重传实现:即发送方只要超过了一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,所以它会重传刚刚的发送过的分组,通过超时计时器实现。信道利用率低。
注意点:可能重传,所以需要保留已发送还未确认的分组。分组和确认分组信息都应该有各自的编号,用来标示每一个分组和确认信息。
连续ARQ协议: 发送方可以连续发送多个分组,然后再等待这些分组的ACK。不必每发完一个分组就停下来等待对方确认。连续ARQ协议通常是结合滑动窗口协议来使用。
接收方一般都是采用累积确认的方式。也就是说接收方不必对收到的分组逐个发送确认。而是在收到几个分组后,对按序到达的最后一个分组发送确认。
拥塞控制就是对发送方拥塞窗口cwnd的调整,TCP常用的拥塞控制四种算法如下: 慢开始(Slow-start),拥塞避免(Congestion Avoidance),快重传(Fast Restrangsmit)和快恢复(Fast Recovery)
当主机开始发送数据时,由小到大逐渐增大拥塞窗口cwnd数值(即 发送窗口数值),试探网络的拥塞情况。这里“慢”指一开始发送报文段拥塞窗口设置小(为1)。每经过一个传输轮次,拥塞窗口就加倍。
使得拥塞窗口(cwnd)按线性规律 缓慢增长:拥塞窗口大小达到慢开始门限ssthresh后,每经过一个往返时间RTT,发送方的拥塞窗口(cwnd)加1。拥塞避免 并不可避免拥塞,只是将拥塞窗口按现行规律缓慢增长,使得网络比较不容易出现拥塞。
接收方 每收到一个失序的报文段后 就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方),而不要等到自己发送数据时才进行捎带确认。发送方只要一连收到3个重复确认就立即重传对方尚未收到的报文段,而不必 继续等待设置的重传计时器到期。
当发送方连续收到3个重复确认后,就执行“乘法减小”算法,把ssthresh门限减半。但是接下去并不执行慢开始算法。 考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将cwnd设置为ssthresh的大小,然后执行拥塞避免算法。如下图:
UDP包头格式(8字节)
TCP包头格式(20字节起)
默认发送端A,接收端B 如果A发给B的确认丢了,该如何? A会超时重传这个ACK吗?不会!TCP不会为没有数据的ACK超时重传。那该如何是好?B如果没有收到A的ACK,会超时重传自己的SYN同步信号,一直到收到A的ACK为止。
第一个包,即A发给B的SYN 中途被丢,没有到达B A会周期性超时重传,直到收到B的确认
第二个包,即B发给A的SYN +ACK 中途被丢,没有到达A B会周期性超时重传,直到收到A的确认
第三个包,即A发给B的ACK 中途被丢,没有到达B A发完ACK,单方面认为TCP为 Established状态,而B显然认为TCP为Active状态: a. 假定此时双方都没有数据发送,B会周期性超时重传,直到收到A的确认,收到之后B的TCP 连接也为 Established状态,双向可以发包 b. 假定此时A有数据发送,B收到A的 Data + ACK,自然会切换为established 状态,并接受A的 Data c. 假定B有数据发送,数据发送不了,会一直周期性超时重传SYN + ACK,直到收到A的确认才可以发送数据
假设是两次握手情况:A发送SYN,由于网络等问题没有确认,导致超时重发了几次。AB建立连接后简单通讯,结束连接。而此时,B又收到了A延迟的SYN,又认为是个正常请求重新建立连接。而这个连接不进行也不中断。不合理
保证A发送的最后一个ACK报文段能到达B
这个ACK报文段有可能丢失,处在LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,B会超时重传这个FIN+ACK报文段,A可以在2MSL时间内收到重传的报文段,再重传一次确认,重启计数器。如果发送了ACK直接关闭不等待2MSL,则无法收到B重传的FIN+ACK报文段,B无法进入CLOSED状态。
防止“已失效的连接请求报文段”出现在本连接中
A发送完最后一个ACK,再经过2MSL,就可以使本连接持续时间内产生的所有报文段都从网络中消失。可以使下一个新连接中不会出现旧连接请求报文段。
时间不宜过短,时间必须大于往返时间 RTT,否则会引起不必要的重传。也不宜过长,这样超时时间变长,访问就变慢了。TCP 通过采样RTT时间 ,然后进行加权平均,算出一个值,而且这个值还是要不断变化的,因为网络状况不断的变化。除了采样 RTT,还要采样 RTT 的波动范围,计算出一个估计的超时时间。由于重传时间是不断变化的,称为自适应重传算法(Adaptive Retransmission Algorithm)。
超时间隔加倍。每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送。
在发送端和接收端都分别设有缓存,通过滑动窗口来实现。 发送端缓存分为:发送已确认、发送未确认、未发送可发送、未发送暂不会发送。 其中之所以将未发送区分为3,4部分,就是考虑到接收方的承受能力。接收方会返回一个Advertised window
通知窗口,其大小应等于发送未确认+未发送可发送大小。超过该窗口接收端做不过来,就不能发送。
接收端缓存分为:接收已确认(还未被应用层读取),还未接收但能接收(即能接收的最大工作量),还未接收也无法接收。 MaxRcvBuffer
:最大缓存的量。其中接收已确认是属于MaxRcvBuffer
中一部分,还没被应用层读取,占用掉的MaxRcvBuffer
的量A。Advertised window
则是MaxRcvBuffer
减去A。
第二部分中,收到包可以不是顺序的,可能存在空档,只有和第一部分连续的可以马上回复,中间空着部分需要等待,即使后面已经来了。
流量控制: 在对包的确认中,同时携带一个窗口大小。假设窗口不变,接收到一个最新的ack,发送端相当于窗口滑动一格,此时有更多的包可发送。如果接收方处理太慢缓存中没空间,通过确认信息修改窗口大小。可以设置成0,则发送方将暂时停止发送。 假设确认窗口减少了1,则发送窗口不会平行右移,仅仅左面的边右移,窗口大小减少。如果接收端一直不处理,接收已确认的包越来越多,则Advertised window
窗口越来越小,直到0,该确认到达发送端时,发送端的窗口也调整为0,停止发送。
这种情况,发送方会定时发送窗口探测数据包,看是否有机会调整窗口的大小。当接收方比较慢的时候,要防止低能窗口综合征,别空出一个字节来就赶快告诉发送方,然后马上又填满了,可以当窗口太小的时候,不更新窗口,直到达到一定大小,或者缓冲区一半为空,才更新窗口。
URL解析:通过DNS解析将URL解析为IP地址。浏览器缓存 - > 本地DNS缓存 -> DNS服务器
建立TCP连接:封装数据,从应用层到链路层,http数据+tcp首部+ip首部+以太网首部
应用层:请求头(方法,地址,协议),请求体
传输层:发起TCP连接,以报文段分割数据。建立连接是三次握手过程
网络层:数据段打包,加入源ip与目的ip。判断是否同一网段,是则根据Mac地址发送,否则查找路由表下一跳地址,以及使用arp协议查询mac地址。
粘包、拆包存在原因:
要发送的数据小于TCP发送缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去,将会发生粘包。
接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包。
要发送的数据大于TCP发送缓冲区剩余空间大小,将会发生拆包。
待发送数据大于MSS(最大报文长度),TCP在传输前将进行拆包。
如何处理:
发送方:对于发送方造成的粘包现象,我们可以通过关闭Nagle算法来解决,使用TCP_NODELAY选项来关闭Nagle算法。
应用层处理:应用程序在处理从缓存读来的分组时,读完一条数据时,就应该循环读下一条数据,直到所有的数据都被处理;但是如何判断每条数据的长度呢?
1.格式化数据:每条数据有固定的格式(开始符、结束符),这种方法简单易行,但选择开始符和结束符的时候一定要注意每条数据的内部一定不能出现开始符或结束符,接收端通过这个边界就可以将不同的数据包拆分开;
2.发送长度:发送每条数据的时候,将数据的长度一并发送,比如可以选择每条数据的前4位是数据的长度,应用层处理时可以根据长度来判断每条数据的开始和结束。