【网络】TCP协议详解(下)

上文介绍了TCP传输控制协议的报头,并且渗透了TCP保证可靠性的策略:如流量控制、按序到达、确认应答机制以及超时重传。本文继续讲解TCP剩下的协议,剩下俩个大话题,难度都比较麻烦。

本文将介绍TCP协议最常见的三次握手和四次挥手、理解为什么需要这样做。另外TCP为了提高效率也做了很多努力,如滑动窗口、延迟应答。另外保证可靠性的另一个措施:拥塞窗口。

三次握手

三次握手的目的是双方可靠的建立连接 。在TCP报文中将标记位SYN设为1。然后向目标服务器发送携带SYN标记位的报文。对端收到报文后,会对报文进行ACK,告知建立连接。

介绍一下这个过程:
以客户端向服务器主动建立连接为例子,讲解一下三次握手。

  1. 客户端会向服务器发送SYN请求建立连接的报文。
  2. 服务器收到报文后要对报文ACK回复,同时服务器也要和客户端建立连接,也要发送SYN建立连接的报文。为了提高效率服务器的SYN+ACK被压缩成一条捎带应答发送给客户端。客户端接收到ACK后,会在OS中创建连接管理,维护连接的属性。同时对服务器进行ACK。
  3. 服务器收到最后一条ACK后,在OS中创建链接管理信息,连接真正的被建立。

 最后一次握手是不可靠的,因为客户端不知道,服务器是否收到ACK报文。但是RST重置位标志保证了双发是可靠的建立链接。

建立一个共识:

建立连接是需要成本的!双方会在内核中开辟结构体,填充相应的字段,比如端口号,序号,缓冲区,窗口大小等。建立连接后,上层调用accept获取文件描述符,将对应的读/写通道提供给上层。所以处于connection没有accpet是不影响的。

常见的问题

为什么要进行三次握手?

本文将从三个角度讲讲为什么需要三次握手?以客户端主动连接服务器为例。


1.最小成本的验证全双工。因为tcp是全双工的,可读可写。

第一次握手表明客户端就有发的能力,并且等待服务器的确认。第二次握手,服务器确认客户端消息,并且表明自己有收和发的能力。第三次客户端确认收到服务器的ack+syn,知道客户端有收的能力。至此客户端和服务器都确认了双发就有收数据和发数据的能力。

2.奇数次握手,客户端会优先建立链接,维护结构体等等。而服务器只有在收到客户端的ack之后,才建立链接。避免了单机程序,恶意发起连接建立引发syn洪水。

3.保证100%可靠的收到建立连接的请求。三次握手本质是四次握手。三次握手当中,有一次是syn+ack是捎带应答。如果将syn + ack拆开的话。就单看俩个朝向上。客户端syn被可靠的接收,另一端 服务器的syn 也被可靠的得知,所以建立连接是可靠的。


四次挥手

四次挥手的目的是断开连接。客户端向服务器发起FIN(结束连接)TCP报文。服务器收到FIN请求后进入WAIT_CLOSE状态,并且向客户端发送ack报文。一般发送完ACK之后,再发送FIN请求断开连接的TCP报文。客户端收到服务器的FIN报文发送ACK报文后进入TIME_WAIT状态。

 为什么不能是三次挥手呢?
客户端主动发起FIN,代表客户端不会给服务器发消息了。C->S朝上是关闭的,而S->C上的朝向是开着的。服务器收到FIN时,可能还有数据需要发送给客户端,短暂的延迟后,才关闭S->C的通道,是为了让客户端将剩余的数据收完。

 TIMEWAIT(等待状态)

主动断开连接的一方会进入TIME_WAIT状态。进入TIME_WAIT状态,连接并不会被彻底释放掉,会保留一段时间,也就导致地址和端口被占用。

存在的意义:

1.最后一次ack丢失,需要重复给服务器

2.网络中可能由于阻塞,存在尚未发送完全的报文。如果立马消失,就会导致上一次没法完的数据,影响新连接。所以一般都要等待旧报文消失。

存在的时间:

2*MSL:报文在网络中存在的时间的2倍。

一般一个MSL是60秒

如何保证旧报文不会影响新连接呢?
策略1:TIME_WAIT延时

策略2:随机一个起始序号


滑动窗口

为了保障效率,TCP允许并发发送大量暂时不需要ack的报文。那么要发多少数据是由对方的接收缓冲区决定的,也就和上文的流量控制有关系,那么要如果控制呢?这就要学习本文的滑动窗口

可以将发送缓冲区想象成一个char 类型的数组,数组中天然的就有下标。

滑动窗口是什么?

在发送缓冲区中,维护了start和end指针,start指针和end指针所包含的区域就是滑动窗口。

滑动窗口的大小是有对方接收能力大小约定的。

粗略的更新规则:

  • start=确认序号。
  • end=确认序号+对方窗口大小。

来自图解TCP/IP的经典图画

主机A发送序号为2000的报文,主机B确认并且告知窗口大小是4000

那么start=2001,end=2001+4000=6001

但是这样解释并不全面。下面更深刻的理解一下滑动窗口

 建立一个共识:

将缓冲区的数据根据滑动窗口划分成三部分,最左边的以及发送,以及ack的数据。中间的可发送的数据。

数据2000-5000的数据被并发发出去。会出现这几种情况

1.最左端的报文丢失:2000的报文丢失/ack丢失、

那么就需要重新发送报文。报文该如何发呢?

如果2000报文丢失,3000、4000、5000正常收到。那么确认序号是多少i?是1001,因为确认序号表示,之前的数据被全部收到。

会发送四条1001的ack给主机A,主机A收到连续三条相同的报文后,会进行重发最左端的报文。

真正收到2001ACK后就会滑动窗口

2.中间丢失呢?

中间丢失会转化为最左端的数据丢失,如果3000丢失,会收到2001ack。重发3000

3.最右报文丢失呢?也会转化会最左端丢失。

如何知道起始的窗口大小?
在三次握手期间,会进行窗口大小的交换。

所以滑动窗口就是流量控制的实际策略。


快重传

刚才提到一个概念,连续收到三条相同序号的ACK后,会立即重发报文。这个机制叫做快重传。

快重传VS超时重传

既然有了快重传,那为什么还要有超时重传?

快重传是提高效率的,如果连续收到三条相同序号的ACK就会重发。但是在极端情况下,数据只有2条。只有4000,5000,就不能发送三条连续报文。所有超时重传是兜底的。二者相互构成TCP重发策略。


拥塞控制

之前谈到TCP保证可靠性,都是都在双方主机上。如果网络出现拥塞,那么就算滑动窗口再大,也不能将数据报文全部发出。否则就会导致网络更加拥堵。

控制单次发送量的多少是由滑动窗口来决定的。也就是说在网络不好的时候,窗口就应该减小。网络好的时候,再由接收端的缓冲区决定。

TCP协议还考虑了网络健康状态,设计了一种策略避免网络的算法——拥塞控制。

如果网络发生了拥挤,说明当前的网络群出现了问题。就发送小部分报文进行试探。如果试探出是正常的,则快速增加单次发送的大小。这就是拥塞控制的特点:前期慢,增长快。

当然,也不能一直无限制的快速增长,增长到某一阈值的时候,增速就放慢。如果网络再次出现拥塞,发送的大小就立马减少到1。

重点关注:
阈值、窗口大小 

这种机制叫做慢启动,先发送少量数据,探探路,摸清楚当前的网络状况后,快速恢复。

再回到流量控制,流量控制的策略是滑动窗口,而滑动窗口不仅依赖于对方窗口大小,还依赖于拥塞窗口的大小。

滑动窗口

  • start=确认序号 ack_seq
  • end=确认序号+min(对端窗口,拥塞窗口)

延迟应答

如果每一份报文都采用ack。那么上层来不及将数据取走,就会导致窗口的减少,而确认序号表示:确认序号之前的报文全部收到。那么就没必要每一个报文都立马进行ACK。

延迟应答是提高效率的策略,每隔N个报文就进行一次ACK,那么上层就有时间取走数据。窗口就更大,发送的数据就更多。


粘包问题

由于TCP协议是面向字节流的,数据是无边界的,发多少就收多少。一份数据的结尾可能读到下一份数据,这就产了一个严重的问题。数据粘包:读到报文的实际数据偏少或者偏多。

为了解决粘包问题,常见的策略

  • 固定长度
  • 变长+自描述字段:比如再报头添加长度
  • 变长+结尾分隔符

另外粘包问题是针对TCP协议,UDP无粘包问题。因为UDP面向数据包,报文本身就有自描述字段,天然是一份完整的报文。


TCP异常

进程终止:OS会自动进行四次挥手,自动关闭链接

重启:自动进行四次挥手,自动关闭链接

机器断电:保活机制

如果机器发生断电:对端的服务会定时发送一个报文,如果在保活期间得不到ACK后会自动关闭链接。但是这个保活时间一般会维持120分钟。不推荐用TCP自带的保活机制,由引用层自己设置。

至此TCP协议的绝大多数的内容都已经介绍完毕了

TCP保证可靠性的策略

  • 流量控制
  • 按序到达
  • 确认应答
  • 超时重传
  • 连接管理
  • 拥塞控制

不仅如此TCP为了提高效率也做了很多准备

提高效率

  • 延迟应答
  • 快重传
  • 滑动窗口
  • 捎带应答

另外TCP效率不一定比UDP慢!TCP是可靠的,UDP是不可靠的。可靠与不可靠是中性的。

  • 29
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深度搜索

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值