1、传输层概述
(1)作用
传输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是用户功能中的最底层。
从传输层的角度,通信的真正端点并不是主机而是主机中的进程。
传输层有分用和复用的功能。“复用” 是指在发送方不同的应用进程都可以使用同一个运输层协议传送数据,“分用” 是指接收方的运输层在剥去报文的首部后能够把这些数据正确交付目的应用进程。
网络层和运输层有明显的区别,网络层为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信。
(2)协议
- 用户数据报协议 UDP(User Datagram Protocol)
- 传输控制协议 TCP(Transmission Control Protocol)
(3)端口
知名端口号:0~1023
登记端口号:1024~49151
客户端短暂端口号:49152~65535
2、UDP
(1)UDP 的特点
① 无连接。发送数据之前不需要建立连接,因此减少了开销和发送数据之前的时延。
② 尽最大努力交付。即不保证可靠交付,因此主机不需要维持复杂的连接状态表。
③ 面向报文的。对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界,UDP 一次交付一个完整的报文。
④ 没有拥塞控制。网络拥塞不会降低源主机的数据发送速率,对一些实时应用的场景(如 IP 电话、实时视频会议等)很有用。
⑤ 支持一对一、一对多、多对一和多对多的交互通信。
⑥ 首部开销小。只有 8 个字节,比 TCP 至少 20 个字节的首部要短。
(2)UDP 的首部格式
用户数据报 UDP 有两个字段:数据字段和首部字段。首部字段很简单,只有 8 个字节,由四个字段组成,每个字段的长度都是两个字节。各字段意义如下:
① 源端口 在需要对方回信时选用。不需要时可用全0。
② 目的端口 目的端口号。这在终点交付报文时必须使用。
③ 长度 用户数据报的长度,最小值为 8 (仅有首部)。
④ 检验和 检测用户数据报在传输中是否有错。有错就丢弃。
用户数据报首部检验和的计算和校验都要计算出一个伪首部。
3、TCP 概述
(1)TCP 的特点
① 面向连接。
应用程序在使用 TCP 协议之前,必须先建立 TCP 连接;传送数据完毕后,必须释放已经建立的 TCP 连接。类似于打电话:通话前要先拨号建立连接,通话结束后要挂机释放连接。
② 一对一。
TCP 连接只能是点对点的(一对一)。
③ 可靠交付。
通过 TCP 连接传送的数据,无差错、不丢失、不重复,并且按序到达。
④ 全双工通信。
通信双方的应用进程在任何时候都能发送和接收数据,TCP 连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。
⑤ 面向字节流。
TCP 中的 “流” 指的是流入到进程或从进程流出的字节序列。
“面向字节流” 的含义:虽然应用程序和 TCP 的交互式一次一个数据块(大小不等),但 TCP 把应用程序交下来的数据仅仅看成是一连串无结构的字节流。TCP 并不知道所传送的字节流的含义。TCP 不保证接收方应用程序锁收到的数据块和发送方应用程序所发出的数据块具有对应的大小关系。但接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样,当然接收方的应用程序必须有能力识别收到的字节流,把它还原成有意义的应用层数据。
(2)TCP 连接
TCP 连接是协议软件提供的一种抽象,每一条 TCP 连接唯一地被通信两端的两个端点(即两个套接字)所确定,即:
TCP 连接 ::= {socket1, socket2} = {(IP1: port1), (IP2: port2)}
IP1 和 IP2 分别是两个端点主机的 IP 地址,port1 和 port2 分别是两端端点主机中的端口号。
4、可靠传输的原理
网络只能提供最大努力的服务,是不可靠的,因此 TCP 必须采用适当的措施才能使得两个运输层之间的通信变得可靠。当出现差错时让发送方重传出现差错的数据,同时在接收方来不及处理收到的数据时,及时告知发送方适当降低发送数据的速度,这样就可以在不可靠的传输信道实现可靠传输。
ARQ(Auto Repeat-reQuest):自动重传请求。
(1)停止等待 ARQ 协议
发送方每发送完一个分组就停止发送,等待接收方确认,在收到确认后再发送下一个分组。
A 是发送方,B 是接收方。
① 无差错情况
A 每发送一个分组后,等待 B 对该分组的确认后,再接着发送下一个分组。
② 出现差错
【发送方】A 发送的分组在传输过程中出错,可能是丢失了,也可能是分组受到干扰出错了
【接收方】这时 B 直接丢弃分组,什么也不做(也不通知 A 受到的分组有差错)。
【解决方案】发送方在每发送完一个分组时设置一个超时计数器,只要超过一段时间仍然没有接收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组,这叫超时重传。反之在超时计时器到期之前收到了相应的确认,就撤销该超时计时器。
- 超时重传机制中发送方要注意的三点:
第一,A 在发送完一个分组后,必须暂时保留已发送的分组的副本(在发生超时重传时使用)。只有在收到相应的确认后才能清楚暂时保留的分组副本。
第二,分组和确认分组都必须进行编号。这样才能明确是哪一个发送出去的分组受到了确认,而哪一个分组还没有收到确认。
第三,超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些。
③ 确认丢失和确认迟到
- 确认丢失
【发送方】超时重传时间内没有收到确认报文,无法确认是发送出错、丢失,还是接收方的确认丢失,超时计时器到期后就要重传。
【接收方】丢弃收到的重复分组,不向上层交付;向发送方发送确认。
- 确认迟到
【发送方】收下迟到的确认,并且丢弃
note: 停止等待 ARQ 协议的缺点
发送方大部分时间都在等待确认,信道的利用率低
使用流水线的 ARQ 可以提高信道利用率
(2)连续 ARQ 协议
① 工作原理
【发送方】维持一个发送窗口,位于发送窗口内的分组都可连续发送出去,而不需要等待对方的确认。
【接收方】可逐个确认,但为了提高效率,可采用累积确认的方式,即接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,表示到这个分组为止的所有分组都已正确收到了。
② 累积确认的特点
- 优点:容易实现,即使确认丢失也不必重传。
- 缺点:不能向发送方反映出接收到已经正确收到的所有分组的信息。
回退N帧协议:如果发送方发送了多个分组,但中间的某个分组丢失了,这时接收方只能对丢失分组之前的分组发出确认,而发送方无法知道丢失分组及后面分组的接收情况,只好把丢失分组及后面的分组重传一次,这叫 Go-back-N,表示需要再退回来重传已发送过的 N 个分组。
5、TCP 报文段的首部格式
前面 20 个字节固定,因此 TCP 首部最小长度是 20 字节。
源端口和目的端口
序号:本报文段所发送数据的第一个字节的序号。
确认号:起到收到对方下一个报文段的第一个数据字节的序号。
数据偏移:TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远。
保留:保留今后使用
控制位1 - 紧急 URG(Urgent):URQ 为 1 表示紧急指针字段有效,告诉系统有紧急数据尽快传送。
控制位2 - 确认 ACK(ACKnowledgment):连接管理,报文数据的确认时使用。
控制位3 - 推送 PSH(Push):PSH 为 1 时,接收方 TCP 收到后会尽快交付应用进程,而不再等到缓存满了再向上交付。
控制位4 - 复位 RST(ReSeT):RST 为 1 表明 TCP 连接中出现严重差错,必须释放连接。
控制位5 - 同步 SYN(SYNchronization) :在连接建立时用来同步序号。
控制位6 - 终止 FIN(FINis):当 FIN = 1 时,表示此报文段的发送方的数据已经发送完毕,并要求释放运输连接。
窗口:接收方让发送方设置其发送窗口的依据,窗口值明确指出了现在允许对方发送的数据量,并且是动态变化的。
检验和:检验和字段检验的范围包括首部和数据两部分。
紧急数据:仅在 URG = 1 时才有意义,指出了紧急数据的末尾在报文段中位置,即使窗口为零也可发送紧急数据。
6、TCP 可靠传输的实现
(1)以字节为单位的滑动窗口
TCP 的滑动窗口以字节为单位,窗口后沿的部分表示已发送且已收到通知,窗口里的序号表示允许发送的序号,窗口前沿之前的数据暂时不允许发送,需要等待收到接收方的确认后前沿往前移才可发送。
描述一个发送窗口需要三个指针:P1、P2 和 P3,如图所示:
小于 P1 的是已发送并已收到确认的部分,而大于 P3 的是不允许发送的部分。
P3 - P1 = A 的发送窗口
P2 - P1 = 已发送但尚未收到确认的字节数
P3 - P2 = 允许发送但当前尚未发送的字节数(又称为可用窗口或有效窗口)
接收方 B 接收窗口大小为20,因为未收到 31 的数据,即使已收到后面的序号 32、33 的数据,返回的确认号仍然是 31。
现在接收方收到了 31、32、33,并返回确认号 33,接收窗口往前滑动 3 个序号,发送方接收到确认,发送窗口也向前滑动 3 个序号大小,现在 A 可以发送序号 51~53 的数据了。
当发送方将发送窗口内的数据都发送出去,但是接收方的确认可能由于网络拥塞滞留,这时发送方发送窗口已满,可用窗口为 0,只能等待接收方的确认报文到达。
(2)超时重传时间的选择
TCP 为了保证可靠传输,要求必须受到对已发送报文的确认,如果超过一定时间未受到确认报文,则重传已发送的报文。这个时间就叫超时重传时间,很明显超时重传时间的大小设置应该更贴近网络的实际情况,如果网络状况好,就设短一点,否则使网络的空闲时间增大,降低了传输效率;网络差就设长一点,否则会引起很多不必要的重传,使网络负荷增大。
TCP 采用了一种自适应的算法:
RTT(报文段的往返时间)、RTTs(加权平均往返时间),RTTs 的计算公式:
新的 RTTs = (1 - α) × (旧的 RTTs) + α × (新的 RTT 样本) // RFC 标准建议 α 值为 1/8,即 0.125
RTTd(RTT 的偏差的加权平均值)、RTO(RetransmissionTime-Out 超时重传时间):
RTO = RTTs + 4 × RTTd
(3)选择确认 SACK
【场景】TCP 的接收方在接收对方发送过来的数据字节流的序号不连续,形成一些不连续的字节块,如果简单按照回退N帧协议处理,意味着要重传第一个未收到的序号数据块及之后的数据,如果能通知发送方已收到了哪些数据(选择确认),就可以让发送方只发送接收方未收到的数据。
7、流量控制
(1)利用滑动窗口实现流量控制
流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。
当发送方收到接收方通知,将窗口缩小为 0 时,发送方将暂时不能发送数据了,必须等接收方通知更新接收窗口大小,但是这个通知又有可能丢失,导致发送方没收到通知。
为了避免双方互相等待死锁,TCP 为每个链接设有一个持续计时器,只要 TCP 连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带 1 字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值。如果窗口仍然是零,那么受到这个报文段的一方就重新设置持续计时器;如果窗口不是零,那么死锁的僵局就可以打破了。
(2)TCP 的传输效率
-
TCP 报文段的发送机制:
① 维持一个变量,它等于最大报文段长度 MSS,缓存中存放的数据达到 MSS 字节时,就组装成一个 TCP 报文段发送出去
② 发送方的应用进程指明要求发送报文段,即 TCP 支持的推送(push)操作
③ 设置一个计时器,计时器期限到了,就把当前已有的缓存数据装入报文段
- 几种提高传输效率的算法
① Nagle 算法
如果发送方缓存的数据较少,则不马上发送数据,而是在下面两种条件下才进行数据发送:
1、已发送的数据都已经收到确认应答
2、缓存中的数据达到最大段长度(MSS)的大小
【优点】提高网络利用率
【缺点】可能会发生某种程度的延迟
② 延迟确认应答
【场景】接收数据的主机如果每次都立刻回复确认应答的话,可能会返回一个较小的窗口,因为接收方刚接收完数,缓冲区已满。
【糊涂窗口综合征问题】
TCP 接收方缓存已满,而交互式的应用进程一次只从接收缓存中读取 1 个字节(这样就使接收缓存空间仅腾出 1 个字节),然后向发送方发送确认,并把窗口设置为 1 个字节(但发送的数据报是 40 字节长,TCP 首部 + IP 数据报首部)。接着,发送方又发来 1 个字节的数据(注意发送方发送的 IP 数据报是 41 字节长)。接收方发回确认,仍然将窗口设置为 1 个字节。这样进行下去,使网络的效率很低。
【解决方案】接收方收到数据不立即返回确认应答,而是延迟一段时间,等接收方缓存腾出一些空闲空间再返回确认应答,如果延迟时间到期空间依然腾不出多少,也依然返回确认应答。
TCP 文件传输中,就采用了两个数据段返回一次确认应答,并且等待一定时间后没有其他数据包到达时也依然发送确认应答。
③ 捎带应答
【场景】交互式应用场景下,如 TELNET 需要对输入的字符进行回送校验,返回的回执数据比较小,如果 TCP 的确认应答和回执数据分两个包发送,效率比较低,在此类通信中,可以通过一个包发送,这种方式叫做捎带应答。
【工作机制】接收方接收到数据后不马上返回确认应答,而是将数据交付给应用层并等其处理生成返回数据后,将数据放到确认应答报文中再发送。
【优点】在线路宽带不富裕时,提高网络利用率,并降低计算机处理负荷。
8、拥塞控制
(1)拥塞的原理
当对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏,这种情况就叫做拥塞。
通过增加一些资源的方式(如扩大节点缓存存储空间、更换更高速率的链路、提高节点处理机的速度)能够解决拥塞问题?
不能,网络拥塞是由多种因素引起的,解决了某方面资源的需求可能到导致对另一方面资源的瓶颈,有点类> 似短板效应。
1、在网络拥塞的情况下,某个节点出现存储空间不足而丢弃分组的情况,如果只是简单扩大存储空间,由于链路和处理机的速度并未提高,这时节点中排队的分组数量增加,导致绝大多数分组的排队等待时间增加,如果因排队超时,发送方只好进行重传,更加剧了拥塞,所以简单扩大缓存的存储空间会造成网络资源的严重浪费,解决不了网络拥塞的问题。
2、简单某段链路或处理机的速度,只会将瓶颈转移到其他地方,只能缓存不能根本上解决问题。
拥塞的实质是整个网络各个部分的资源不匹配,只有所有部分都平衡了,问题才能得到解决。
流量控制跟拥塞控制有什么区别?
流量控制是接收方通过接受窗口大小,控制发送方发送窗口大小,防止发送方发送数据过快,导致接收方处理不过来,属于点对点通信量的控制
拥塞控制是一个全局性的过程,涉及到所有的主机、路由器以及与降低网络传输性能有关的所有因素。防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。
(2)TCP 的拥塞控制方法
慢开始(slow-start)、拥塞避免(congestion avoidance)、快重传(fast retransmit)和快恢复(fast recovery)。
- 慢开始
【算法思路】
当主机开始发送数据时,由于并不清楚网络的负荷情况,所以如果立即把大量数据字节注入网络,那么就有可能引起网络发生拥塞。较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。
【处理过程】
慢开始门限值 ssthresh 决定了拥塞窗口达到多大时要执行什么算法。
① 当 cwnd < ssthresh 时,使用慢开始算法;
② 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法;
③ 当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞避免算法。
在拥塞窗口 cwnd 达到门限值之前,发送方每一轮次收到确认应答后,cwnd 就增大为原来的两倍;达到门限值后,执行拥塞避免算法。
PS. 慢开始只是表示初始发送数据少,不代表发送速率增长速度慢,实际上是指数级增长非常快。
- 拥塞避免
【算法思路】
让拥塞窗口 cwnd 缓慢地增大,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,而不是像慢开始阶段那样加倍增长。拥塞避免阶段有“加法增大” 的特点,按线性规律缓慢增长,使网络比较不容易出现拥塞。
【处理过程】
在执行拥塞避免算法阶段,当网络出现超时时,发送方判断为网络拥塞,调整门限值为当前拥塞窗口的一半,即 ssthresh = cwnd / 2,同时拥塞窗口重置为 1,即 cwnd = 1,进入慢开始阶段。
- 快重传和快恢复
【算法原理】
① 快重传
【场景】有时,个别报文段会在网络中丢失,但实际上网络并未发生拥塞。如果发送方迟迟收不到确认,就会产生超时,就会误认为网络发生了拥塞,导致发送方错误地启动慢开始,把拥塞窗口 cwnd 又设置为 1,因而降低了传输效率。
【方案】接收方不要等待自己发送数据时才进行捎带确认,而是要立即发送确认,即使收到了失序的报文段也要立即发出对已收到的报文段的重复确认,当发送方一连收到 3 个重复确认,就知道接收方确实没有收到某个报文段,因而应当立即进行重传。
② 快恢复:
发送方知道只是丢失了个别的报文段,于是不启动慢开始,而是执行快恢复算法,调整发送方门限值 ssthresh = cwnd / 2,同时设置拥塞窗口 cwnd = ssthresh = 8,并开始执行拥塞避免算法。
(3)总结
拥塞控制的流程如下:
拥塞窗口 cwnd,接收方窗口 rwnd,发送方发送窗口的上限值 = Min[rwnd, cwnd]。
① 当 rwnd < cwnd,接收方的接收能力限制发送方窗口大小;
② 当 cwnd < rwnd,网络的拥塞程度限制发送方窗口大小。
9、主动队列管理 AQM
【问题背景】
路由器采取分组丢弃策略,即按照先进先出(FIFO)规则处理分组,当队列已满时,则丢弃后面到达的分组,这叫尾部丢弃策略。
丢失的分组会导致发送方出现超时重传,发送方转而执行慢开始算法,不同分组属于不同 TCP 连接,导致很多 TCP 同时进入慢开始状态,这种现象称为全局同步。
【解决方案】
主动队列管理 AQM:不等到路由器的队列长度已经达到最大值时才不得不丢弃后面到达的分组,而是在队列长度达到某个警惕值时就主动丢弃到达的分组,这样就提醒了发送方放慢发送的速率,因而有可能使网络拥塞的程度减轻,甚至不出现网络拥塞。
10、连接管理
TCP 是面向连接的协议,运输连接有三个阶段:连接建立、数据传送、连接释放。
TCP 连接建立过程要解决的几个问题:
① 使每一方能够确知对方的存在;
② 允许双方协商一些参数(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等);
③ 能够对运输实体资源(如缓存大小、连接表中的项目等)进行分配。
(1)连接建立
TCP 建立连接的过程叫做握手,握手需要在客户和服务器之间交换三个 TCP 报文段,即三次握手。
最初客户端和服务端都处于 CLOSED(关闭)状态,A(Client)主动打开连接,B(Server)被动打开连接。
一开始,B 的 TCP 服务器进程先创建传输控制块 TCB,准备接受客户进程的连接请求。然后服务器进程就处于 LISTEN(收听)状态,等待客户端的连接请求。如有,即作出响应。
第一次握手:A 的 TCP 客户进程也是首先创建传输控制块 TCB,准备接受客户进程的连接请求。然后在打算建立 TCP 连接时,向 B 发出连接请求报文段,这时首部中的同步位 SYN = 1,同时选择一个初始序号 seq = x。TCP 规定,SYN 报文段(即 SYN = 1 的报文段)不能携带数据,但要消耗掉一个序号。这时,TCP 客户进程进入 SYN-SENT(同步已发送)状态。
第二次握手:B 收到连接请求报文段后,如同意建立连接,则向 A 发送确认。在确认报文段中应把 SYN 位和 ACK 位都置 1,确认号是 ack = x + 1,同时也为自己选择一个初始序号 seq = y。请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。这时 TCP 服务器进程进入 SYN-RCVD(同步收到)状态。
第三次握手:TCP 客户进程收到 B 的确认后,还要向 B 给出确认。确认报文段的 ACK 置 1,确认号 ack = y + 1,而自己的序号 seq = x + 1。TCP 的标准规定,ACK 报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍是 seq = x + 1。这时,TCP 连接已经建立,A 进入 ESTABLISHED(已建立连接)状态。当 B 收到 A 的确认后,也进入 ESTABLISHED(已建立连接)状态。
① 为什么 A 最后还要发送一次确认?/ 为什么两次连接不可以?
为了防止已经失效的连接请求报文段突然又传送到了B,因而产生错误。比如下面这种情况:
A 发出的第一个连接请求报文段并没有丢失,而是在网路结点长时间滞留了,以致于延误到连接释放以后的某个时间段才到达 B。本来这是一个早已失效的报文段。但是 B 收到此失效的链接请求报文段后,就误认为 A 又发出一次新的连接请求。于是就向 A 发出确认报文段,同意建立连接。
对于上面这种情况,如果不进行第三次握手,B 发出确认后就认为新的运输连接已经建立了,并一直等待 A 发来数据。B 的许多资源就这样白白浪费了。
如果采用了三次握手,由于 A 实际上并没有发出建立连接请求,所以不会理睬 B 的确认,也不会向 B 发送数据。B 由于收不到确认,就知道 A 并没有要求建立连接。
② 为什么不需要四次挥手?
有人可能会说 A 发出第三次握手的信息后在没有接收到 B 的请求就已经进入了连接状态,那如果 A 的这个确认包丢失或者滞留了怎么办?
我们需要明白一点,完全可靠的通信协议是不存在的。在经过三次握手之后,客户端和服务端已经可以确认之前的通信状况,都收到了确认信息。所以即便再增加握手次数也不能保证后面的通信完全可靠,所以是没有必要的。
③ Server 端收到 Client 端的 SYN 后,为什么还要传回 SYN?
接收端传回发送端所发送的 SYN 是为了告诉发送端,我接收到的信息确实就是你所发送的信号了。
SYN 是 TCP / IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement[汉译:确认字符,在数据通信传输中,接收站发给发送站的一种传输控制字符。它表示确认发来的数据已经接受无误])消息响应。这样在客户机和服务器之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务器之间传递。
④ 传了 SYN,为什么还要传 ACK?
双方通信无误必须是两者互相发送信息都无误。传了 SYN,证明发送方到接收方的通道没有问题,但是接收方到发送方的通道还需要 ACK 信号来进行验证。
⑤ 当最后一次握手(A 发出的 ACK 确认报文段)B 没收到时,服务端如何处理?
当服务端等待确认报文超时时,不会重发 SYN + ACK 报文段,而是直接发送 RTS 报文段,进入 CLOSED 状态,,这样做的目的是为了防止 SYN 洪泛攻击。
(2)连接释放
数据传输结束后,通信的方法都可释放连接。现在 A 和 B 都处于 ESTABLISHED 状态。
第一次挥手:A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。A 把连接释放报文段首部的终止控制位 FIN 置 1,其序号 seq = u,它等于前面已传送过的数据的最后一个字节的序号加 1。这时 A 进入 FIN-WAIT-1(终止等待 1)状态,等待 B 的确认。请注意,TCP 规定,FIN 报文段即使不携带数据,它也消耗掉一个序号。
第二次挥手:B 收到连接释放报文后即发出确认,确认号是 ack = u + 1,而这个报文段自己的序号是 v,等于 B 前面已传送过的最后一个字节的序号加 1。然后 B 就进入 CLOSE-WAIT(关闭等待)状态。TCP 服务器进程这时应通知高层应用程序,因而从 A 到 B 这个方向的连接就释放了,这时的 TCP 连接处于半关闭(half-close)状态,即 A 已经没有数据要发送了,但 B 若发送数,A 仍要接收。也就是说,从 B 到 A 这个方向的连接并未关闭,这个状态可能会持续一段时间。A 收到来自 B 的确认后,就进入 FIN-WAIT-2(终止等待 2)状态,等待 B 发出的连接释放报文段。
第三次挥手:若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接。这时 B 发出的连接释放报文段必须使 FIN = 1。现假定 B 的序号为 w(在半关闭状态 B 可能又发送了一些数据)。B 还必须重复上次已发送过的确认号 ack = u + 1。这时 B 就进入 LAST-ACK(最后确认)状态,等待 A 的确认。
第四次挥手:A 在收到 B 的连接释放报文段后,必须对此发出确认。在确认报文段中把 ACK 置 1,确认号 ack = w + 1,而自己的序号是 seq = u + 1(根据 TCP 标准,前面发送过的 FIN 报文段要消耗一个序号)。然后进入 TIME-WAIT(时间等待)状态。请注意,现在 TCP 连接还没有释放掉。必须经过时间等待计时器(TIME-WAIT timer)设置的时间 2MSL 后,A 才进入到 CLOSED 状态,然后撤销传输控制块,结束这次 TCP 连接。当然如果 B 一收到 A 的确认就进入 CLOSED 状态,然后撤销传输控制块。所以在释放连接时,B 结束 TCP 连接的时间要早于 A。
⑦ 为什么 A 在 TIME-WAIT 状态必须等待 2MSL 的时间?
1、为了保证 A 发送的最后一个 ACK 报文段能够到达 B。这个 ACK 报文段有可能丢失,因此使处在 LAST-ACK 状态的 B 收不到对已发送的 FIN + ACK 报文段的确认。B 会超时重传这个 FIN + ACK 报文段,而 A 就能在 2MSL 时间内收到这个重传的 FIN + ACK 报文段。接着 A 重传一次确认,重新启动 2MSL 计时器。最后,A 和 B 都正常进入到 CLOSED 状态。如果 A 在 TIME-WAIT 状态不等待一段时间,而是在发送完 ACK 报文段后立即释放连接,那么就无法收到 B 重传的 FIN + ACK 报文段,因此也不会再发送一次确认报文段。这样,B 就无法按照正常步骤进入 CLOSED 状态。
2、防止已失效的连接请求报文段出现在本连接中。A 在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。
⑧ 为什么第二次和第三次挥手不能合并,这两次挥手中间的等待是为了什么?
当服务器执行第二次挥手之后, 此时证明客户端不会再向服务端请求任何数据, 但是服务端可能还正在给客户端发送数据(可能是客户端上一次请求的资源还没有发送完毕),所以此时服务端会等待把之前未传输完的数据传输完毕之后再发送关闭请求。
⑨ 保活计时器的作用?
除时间等待计时器外,TCP 还有一个保活计时器(keepalive timer)。设想这样的场景:客户已主动与服务器建立了 TCP 连接。但后来客户端的主机突然发生故障。显然,服务器以后就不能再收到客户端发来的数据。因此,应当有措施使服务器不要再白白等待下去。这就需要使用保活计时器了。
服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是两个小时。若两个小时都没有收到客户端的数据,服务端就发送一个探测报文段,以后则每隔 75 秒钟发送一次。若连续发送 10个 探测报文段后仍然无客户端的响应,服务端就认为客户端出了故障,接着就关闭这个连接。