TCP协议
TCP---传输控制协议
是一种面向连接的可靠传输协议。
面向连接:指的是数据传输之前,收发双方需要先建立一条逻辑通路。
无面向连接:指的是数据可以自由传输,无需建立逻辑通路。
确认序列号:是收到的报文的序列号收到的数据部分字节大小。
确认机制:没收到一个发送方发出的数据,都需要回复一个确认报文。
- 表明接收方期望收到发送方发送的下一个字节的序号。
- 代表接收方已经收到了确认序列号之前的所有字节数据。
累计确认。
标志位:
- 紧急位URG:报文段中包含紧急数据,是高优先级的数据,应尽快传输,不在缓存队列中排队。确认位ACK:当确认位置位1,则确认序列号有意义。在连接连接以后所有传输的报文段都必须把ACK置位1。
2、推送位PSH:接收方应尽快将数据交付给应用程序,不再等待缓存填满再向上提交。
3、复位RST:表明TCP连接中出现错误,必须释放连接,然后重新建立连接同部位SYN:表明这是一个连接请求报文
4、终止位FIN:表明发送方数据已完全发送,要求释放连接。
TCP的可靠性:确认、重传、排序、流控。
TCP的重传机制
RTO/RTT
RTO被称为超时重传时间。
RTT---指的是发送端将数据发出后,到他接收到对端反馈的确认报文之间的这段时间。
超时重传
超时重传是TCP最基本的重传机制。当发送端发送数据包后,会启动一个计时器,称为重传定时器。如果在定时器到期前,发送端没有收到接收端的确认应答(ACK),就会认为数据包可能丢失,并重新发送该数据包。RTO是一个动态变化的值,它会根据网络状况不断调整,以避免不必要的重传和网络拥塞。
超时间隔加倍机制。当连续多次未收到确认报文,设备会认为是网络拥塞过大,将重传时间加倍,因为如果按照原本的重传时间发送报文,很可能造成网络拥塞的加剧。
快速重传
快速重传是一种改进的重传机制,旨在减少因单个数据包丢失而导致的整个数据流传输延迟。当发送端连续收到三个相同的ACK时,表明中间有一个数据包丢失,发送端会立即重传这个被认为丢失的数据包,而不必等到超时。这种机制通过增加重传的触发门槛,提高了对丢包检测的准确性,从而优化了网络资源的利用和数据传输的效率。
因为TCP协议无法直接发送一个否认确认报文(没有办法直接发送一个数据报文段,告诉对端自己哪个报文没有收到),所以,TCP将采用冗余ACK的方式来完成缺失报文通告。
SACK机制---选择确认机制
TCP在可选项字段中,添加了一个变量。该变量中携带的就是自己已经收到的数据信息。
TCP的确认是累积确认机制,正确接收失序的报文段是不会被接收方逐个确认的。因此,发送方在重传的时候,需要将冗余ACK报文及之后的报文段都重新发送一遍。----导致资源浪费。
选择确认机制,不是所有运行TCP协议的设备都支持的。该机制会在TCP三次握手的前两次SYN报文中进行协商。
排序机制
大字节数由MSS控制。该参数是需要在TCP连接握手的过程中,通过前两次SYN报文段来进行参数协商。
如果双方的MSS数值不同,则选择数值较小的作为传输标准。
MSS受到MTU的限制。
MTU: 大传输单元,指的是数据链路层在封装成帧时所允许携带的 大数据量,在以太网当中,
MTU数值为1500字节。
MSS:数据段中携带的数据字节数。
MSS=MTU-IP首部-TCP首部
通过序列号字段,保证分段的有序性。将根据序列号的大小,将乱序的报文段进行重组。
确认机制是TCP保障可靠性的核心点。
TCP协议保证对方能够收到本端发送的数据段的方式,就是让对方回复一个确认报文段。这是确认机制的做法。
确认报文是唯一一种不需要被确认的数据段信息。
流量控制机制
是属于TCP的传输效率问题。
采用的机制为窗口机制。
滑动窗口
TCP头部中的”窗口值“是TCP实现流控的核心参数。
窗口的大小是可以指定的,该参数的大小指的是无需等待确认应答,而可以继续发送数据包的最大量。
窗口的大小,其实体现的就是接收缓存区的大小。
TCP要求发送方依据对方的接收窗口(rwnd)来控制数据的发送量。 初,TCP的接口窗口===接收缓存区大小。接口窗口会随着时间的增长而动态变化。
窗口关闭
窗口的大小是接收端根据自己的缓存空间的剩余量来决定的一个动态变化的数值,那么这个剩余量就有归0的可能性。也就代表此时接收方所有缓存空间均已占用并且没能及时处理里面的资源。
所以,当接收方反馈窗口值为0时,那其实就是在通知发送方,别再发送数据,处理不过来。
该机制存在风险:接收方通过确认ACK报文来通知发送方自己的窗口大小。理论上,如果接收方将自己的缓存里的数据清空后,将反馈一个窗口值非0的报文来通知对端,可以继续发送数据了。但是如果这个非0的ACK报文在重传过程中丢失。----会引发风险,因为确认报文丢失不会触发重传机制。所以,客户端依然处于窗口关闭状态,不会发送数据,在等待服务器的响应。而服务器也在等待客户端发送数据。此时,两者进入到死锁状态。
解决方式:客户端周期性发送窗口探测报文,该报文只包含TCP首部信息。通过触发TCP确认机制,来让服务端发送确认报文,从而告知客户端,此时的窗口大小。打破死锁现象。
窗口大小仅仅是实现了将TCP数据传输的效率提高(不需要确认);但是并没有看到所谓的流量控制,而真正的流量控制是由窗口关闭机制实现的。
窗口扩大因子
TCP选项字段中的窗口扩大因子,可以解决首部中窗口值过小的问题。因为首部中窗口值大小仅为16bit,最大值为65536。
窗口扩大因子占据3字节大小。取值仅为0-14。是用来将TCP的窗口的值左移的位数,使得原本的窗口值加倍。
窗口扩大因子,只能出现在同步报文段中,否则将被忽略。
拥塞控制机制
中间链路的处理能力--->拥塞控制机制网络中对资源需求量超过了资源的可用量的情况,被称为拥塞。
如果出现了拥塞情况。--->分组丢失。重传--->网络的拥塞情况加剧。
1、慢启动(Slow Start):
初始时,发送方从小的发送窗口开始,逐步增加数据发送量。
每次收到一个确认(ACK),窗口大小就加倍。
指数增长方式可以快速找到网络的可用带宽。
应用场景:新连接建立时或重传超时后。
TCP会设定一个慢启动门限来评判。评判是否要停止慢启动的机制。
当拥塞窗口<门限,继续使用慢启动算法
当拥塞窗口>门限,此时将慢启动算法切换为拥塞避免算法。
当拥塞窗口=门限,两者均可使用
2、拥塞避免:
当窗口大小达到一定阈值慢启动阈值后,进入拥塞避免阶段。
此时,窗口大小以线性方式增长,每个往返时间(RTT)增加一个最大报文段长度(MSS)。
较慢的增长速度能更稳定地探测网络容量。
拥塞避免
在一个RTT时间线内,拥塞窗口只增加一个MSS。
拥塞避免算法,不是说直接避免拥塞,而是通过降低窗口的增大速率而使得网络不容易出现。
应用场景:网络状况良好,没有丢包时。
3、快速重传:
当发送方收到三个重复的ACK时,立即重传丢失的数据包。
无需等待重传计时器到期,减少了等待时间,加快了恢复过程。
- 快速恢复:
如果网络中没有发生拥塞,那么拥塞窗口就会无时无刻的增长下去。
但是如果出现了拥塞,那么这个增长必须停止。
在快速重传后,TCP执行快速恢复算法。
将拥塞窗口设置为慢启动阈值的值加上3个报文段的大小。
然后进入拥塞避免阶段,窗口大小以线性方式增长。
TCP的拥塞控制状态机通过这些机制动态调整拥塞窗口的大小,以适应网络环境的变化,确保网络吞吐量最大化且不产生拥塞。
如何提高网络利用率
延迟确认应答机制
收到数据以后不立即返回确认报文,而是延迟一段时间。
1、在没有收到2*MSS的数据为止,不做确认应答。
2、其他情况, 大概延迟0.5秒发送确认应答。
捎带应答
TCP的确认应答和回执数据可以通过一个数据包进行发送。
延迟确认机制和捎带应答一般共同使用。
TCP的面向连接
TCP的三次握手
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接.
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
SYN:同步序列编号(Synchronize Sequence Numbers)
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕。
TCP连接的断开
TCP的四次挥手
1.第一次挥手:客户端发送一个FIN,用来关闭客户端到服务器的数据传送,客户端进入fin_wait_1状态
2.第二次挥手:服务端收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1,服务端进入Close_wait状态。此时TCP连接处于半关闭状态,即客户端已经没有要发送的数据了,但服务端若发送数据,则客户端仍要接受
3.第三次挥手:服务端发送一个FIN,用来关闭服务端到客户端的数据传送,服务端进入Last_ack状态
4.第四次挥手:客户端收到FIN后,客户端进入Time_wait状态,接着发送一个ACK给服务端,确认后,服务端进入Closed状态,完成四次挥手。
有关TCP的问题
问题一:初始序列号是什么产生的?为什么是随机值,而不是固定值?
初始序列号--->ISN:初始序列号产生是通过源地址、目的地址、源端口、目的端口和一个随机因子通过哈希算法计算得出的。后续又加入了时间因子。
出于安全性考虑,如果被知道了初始序列号,那么很容易可以构造出一个在对方窗口内的序列号。
从而伪造出TCP报文,实现TCP会话劫持。
TCP序号绕回问题。
重复序号:当序号绕回后,之前已经使用过的序号可能会再次出现,导致接收方错误的将重复的报文段当做新的报文段处理。从而丢弃正常的报文。
延迟确认:因为延迟确认是收到一定数量的数据后才发送,而序号绕回会导致延迟确认的触发时间延后,从而降低数据传输的效率。
解决思路:使用时间戳选项来增加序号的有效范围。
问题二:什么是时间戳?
TCP时间戳--->记录数据报文发送的时间,其中有两个字段,分别为发送方时间;回显时间。
发送方发送数据时,将本地时间记录在发送方时间中。
接收方收到数据报文后,将收到的时间戳原封不动的返回给发送方,并在其中记录自己发送报文的时间。
发送方收到回应报文后,根据报文中的回显时间字段来判断该报文是否是正确的报文,如果是,则根据该时间计算RTT数值,并计算RTO数值。
时间戳是双向选择,需要在TCP连接建立阶段进行协商。
问题三:是否可以使用“两次握手报文”建立连接
采用三次握手形式,不是因为两次握手无法建立连接,而是为了防止已经失效的连接请求报文突然又传送到TCP服务端,从而导致服务端回复信息,建立连接,凭空消耗资源。
问题四:三次握手如何阻止历史连接
当客户端发送连接建立请求报文后,因为网络阻塞,导致客户端重新发送一个连接建立请求报文,这两个报文的序列号不同(因为为初始序列号)。
当网络阻塞减小时,可能旧的报文先到达服务端,而导致服务端回复SYN+ACK报文。此时服务端处于同步已接收状态(SYN-RCVD),但是此时对于客户端而言,服务端回复的报文是错误的报文,因为其确认序列号与客户端将要发送的报文的序列号不匹配,则客户端发送RST报文,断开连接。
当连接断开,服务端恢复到侦听状态,此时客户端发送的第二个连接请求报文到达。之后,正常建立TCP连接。如果是两次握手,那么服务端在收到旧的SYN报文后,会直接进入到连接已建立状态。在该状态意味着已经可以发送数据,可能会存在数据传输。但是又因为此时的连接对于客户端而言时错误的,所以此时服务端传输的数据客户端不会接收。
问题五:如果已经建立了连接,但是客户端突然故障,怎么办?
TCP设计了一个保活计时器。
如果客户端出现故障,服务端不能一直等待下去,因为会白白浪费资源。
服务端没收到一次客户端的请求后都会复位保活计时器,一般为2小时,当保活计时器为0时,服务端主动发送探测报文,并每隔75秒发送一次。如果连续十次报文都没有接收到对端回复,则服务端认为客户端出现故障,关闭连接。
问题六:如果一个TCP连接存在两个客户端,是否可以正常建立连接
可以。因为谁先发送连接请求谁为客户端。