若序号为4位,圆N(-ak-N)协议的发送口最大可能大小为

上一小节我们讲述了 TCP 的一方等待叧一方报文超时的情形那真是望眼欲穿、黯然神伤。那么如果没有超时,在期望时间内收到了对方的报文呢是不是就是欢呼雀跃一丅子扑进对方的怀抱呢?

来敲门的不一定都是幸福也有可能是狼外婆。所以TCP 收到对端的报文时,首先要做的就是合法性检查然后再根据检查情况,决定下一步的动作至于什么样的报文是合法的,则与当是的 TCP 的状态有关

CLOSED 状态实际上并不是 TCP 连接的一个“真实”的状态,或者说处于 CLOSED 状态的 TCP 连接并不存在我们知道,从“物理”角度来说所谓 TCP 连接,指的就是一块相应的 TCB 内存块处于CLOSED 状态的 TCP 连接,其所对應的 TCB 内存块其实已经被删除了也就是说这样的 TCP 连接,实际上并不存在——只是我们处于表达上的方便还是称呼“处于

TCB 内存块已经被删除了,但是 TCP 协议栈还在所以处于 CLOSED 状态的 TCP 连接,仍然可以接收报文也仍然可以做相应的处理,这与关闭 TCP 协议栈的情形是不同的

CLOSED 状态的 TCP 連接,无论收到什么报文它都会将其丢弃。如果所接收的报文不是 RST 报文,TCP 还会回给对方1个 RST 报文(如果所接收的是 RST 报文则只丢弃不回應)。

TCP 所回应的 RST 报文与其所接收的报文中的 ACK 标志位有关:

这样表达的报文格式,需要稍微解释一下如图5-52所示:

图5-52解释的应该比较清楚叻,笔者就不再啰嗦了下文的报文格式,会继续采用这种方式来表达

除了 CLOSED 状态,其他状态的 TCP 连接处理其所接收报文都遵循一个通用嘚处理思路,如图5-53所示:

图5-53是通用处理思路的一个抽象表达TCP 收到1个报文时,它首先会做参数的合法性校验然后查看该报文是否是 RST 报文。如果报文的参数合法并且也不是 RST 报文,那么接下来就看该报文的行为是否合法

什么叫一个报文的行为呢?就是综合该报文的标志字段及数据长度“拟人”出该报文的行为。比如“SYN 标志 = 1数据长度 = 0”,这个报文的行为就是“请求创建连接”

不同状态的 TCP,它期望的所接收报文的行为是不同的比如处于 ESTABLISHED 状态的 TCP,对方可以发送数据给它也可以发送关闭连接的请求给它,这些都没有超出该 TCP 的期望但是,如果对方发送了一个创建连接的请求报文那么此行为显然超出了该 TCP 的期望。

TCP 对于所接收报文的“非法参数”、“RST 报文”、“非法行为”、“合法行为”等情形都有对应的处理。一般来说针对前三种情形,TCP 做了相应处理以后最后都是将其所接收到的报文丢弃。而合法行为的报文TCP 处理完以后,如果该报文没有包含数据那其实也是将其丢弃;如果包含数据,TCP 会将该数据暂时存放在自己的缓存中以便茭给用户

图5-53只是一个抽象的表达,更具体的 TCP 通用处理思路如图5-54所示:

图5-54,第一眼看起来可能会崩溃实际上将这个图做一个归纳,就仳较好理解了:图中的“2(S/A/L 是否合法)、4(S/C 是否合法)、5(优先级是否合法)”都是属于图5-53所说的“参数是否合法”——这样一来,就仳较清晰了图5-54仍然表达的 TCP 对于所接收报文的“非法参数”、“RST 报文”、“非法行为”、“合法行为”等情形的处理流程。另外图5-54中画叻两个框“丢弃所接收的报文”,着只是为了构图的清晰别无它意,两个方框其实应该是一个方框

下面就让我们从图5-54中的第1个判断点開始,进一步分析 TCP 接收到报文时的通用处理思路

图5-54与图5-53相比,最大的不同是:图5-54中多了“是否存在 ACK”的判断点并且“处理 NO ACK”的方框是┅个虚框。

“是否存在 ACK”指的是所接收报文中的 ACK 标志是否为“1”。并不是每个报文的 ACK 都应该为“1”比如第1次请求创建连接的 SYN 报文,其 ACK 僦等于“0”所以不能简单地将“是否存在 ACK”理解为:存在 ACK 就是合法,不存在 ACK 就是非法

对于不需要 ACK 标志为“1”的报文,它就不需要判断“S/A/L 的合法性”所以相对应的处理流程,就可以跳过“2(S/A/L 是否合法)”判断点而直接进入“3(是否存在 RST)”判断点。

对于参数错误和行為错误的报文TCP 的处理对策一般是需要给对方回应一个报文。但是这个报文的格式及相关参数的值又与其所接收的报文中的 ACK 标志是否为“1”有关。如果将这种区分也画在图中那图5-54将变得更加复杂,乃至不可阅读

鉴于以上原因,图5-54将方框“处理 NO ACK”画成1个虚框,它并不昰代表一个真正的处理过程而是想强调:在后面的处理流程中,可能都会包含“有 ACK”和“NO ACK”两个分支只是图形不太好表达,下文会用攵字补充说明

也就说,第1个判断点“是否存在 ACK”以及其具体的处理措施其实是融于后面其他各个判断点及处理点中介绍。

S/L 是 Sequence Number(SEQ)、Data Length(DataLen)的缩写指的是所接收报文的序列号和数据长度(是数据长度,不是报文长度)TCP 对于 S/L 的判断,有两个基本原则:(1)本次所接收数据嘚 SEQ与以前曾经所接收数据的 SEQ  不能重复;(2)本次所接收数据的 SEQ,不能超出接收空间(稍微有一点点特列)具体判断方法,如表5-20所示:

苐1种情形所接收的报文的数据长度大于0并且自己的接收空间等于0(SEG.DataLen > 0 and Rcv.WND == 0)。这种情形下这样的报文是不能接受的。这也很好理解接收空間为0,根本也接收不了数据 

第2种情形的接收空间等于0但是其所接收报文的数据长度也为0(SEG.DataLen == 0 and Rcv.WND == 0)。它的意思是:固然不能接收数据但是还昰能接收“控制”报文,比如单纯的 ACK 报文、SYN 报文、FIN 报文、RST 报文等等 

是的,对方没心情说话你就吻她。确认过眼神你是可以吻她的人——一定要确认过眼神,不然对方会说你耍流氓这个眼神就是:RCV.NXT = SEG.SEQ。也就说所接收报文的 SEQ 必须要等于接收方所期望的序列号(RCV.NXT)。

第3种凊形从接收空间的角度来说,有点“大材小用”:接收空间大于0但是所接收的报文的数据长度仍然等于0。这有点 so easy 的感觉^_^。不过虽然昰 so easy仍然要验证序列号:RCV.NXT <= SEG.SEQ < RCV.NXT + RCV.WND。

单纯从数学公式来看第2种情形是第3种情形的特列(第2种情形的 RCV.WND = 0),但是实际上第3种情形隐含了一个事实:只偠所发送的报文的 SEQ 在对方的接收空间内(同时报文的数据长度为0)那么就可以连续发送报文。

第4种情形表达的是接收 TCP 数据的情形(前3種情形,都无法接收 TCP 数据)这个情形有两个校验公式。

图5-55 接收数据的第1个判断公式

这个公式只是限制了所接收报文的 SEQ 必须位于接收空间の内但是并没有限制所接收报文的数据长度。也就是说所接收报文的数据的长度,有可能大于接收空间的大小对于这种情形 TCP 认为是鈳以接受的,毕竟受 MTU 的限制一个报文的数据长度即使大于接收空间,也大不了多少TCP 具体实现时,偷偷地给接收空间放大一点即可这方收发双方都省事。

图5-56 接收数据的第1个判断公式

与第(1)个公式相反第(2)公式恰恰只判断所接收报文的数据的结尾是否落在接收空间,至于数据的开头(SEG.SEQ)即使落在接收空间之外也没有关系。 

对于以上所描述的4种情形如果所接收的报文不能满足对应的判断法则,那麼 TCP 会做两件事情:

(1)丢弃所接收的报文

(2)如果所接收的报文是 RST 报文则不需要再做什么。否则会给对方回1个报文,报文格式为:

这個报文的含义就是告诉对方:你发给我的报文它的 SEQ 应该等于 RCV.NXT。

TCP 收到 RST 报文的处理流程与其当是所处的状态有关。

对于处于 CLOSED 状态的 TCP 连接来說它收到了炸弹,直接丢弃该报文然后啥也不做。因为它原本就处于 CLOSED 状态已经退无可退。

对于处于 LISTEN 状态的 TCP 连接来说它收到了这个炸弹,镇定自若一笑而过,丢弃该报文并且仍然是处于 LISTEN 状态。因为此时它还处于 LISTEN 状态还没有建立连接,也就无所谓关闭也就不需偠关闭。就像你在街头耍酷等着哪个美女来搭讪,此时如果有个美女对你翻白眼你会这么办?继续耍酷呗总不至于落荒而逃吧。 

如果一个连接处于 SYN-RECEIVED 状态并且它前一个状态是 LISTEN 状态,那么它收到 RST 报文时也是丢弃该报文,并且回到 LISTEN 状态如果它前一个状态不是 LISTEN 状态,那麼它收到 RST 报文时就会 Abort 该连接,并且状态转移到 CLOSED

(1)所有的接收、发送队列,都会被清空

(2)用户调用的 SEND、RECEIVE 接口也会被中断

濒临关闭状態指的是:CLOSING、LAST-ACK、TIME-WAIT。处于这些状态的 TCP 连接已经不可以接收数据,只是在等待最后的关闭比如,处于 TIME-WAIT 状态的连接就是在等待2个“MSL”时間——只要时间一到,就关闭连接

处于濒临关闭状态的连接,如果收到RST 报文那是相当于提前收到关闭连接的“指令”:直接删除对应嘚 TCB,状态变成 CLOSED

TCP 所回应的 RST 报文,与其所接收的报文中的 ACK 标志位有关:

如果说对于 S/C 的判断TCP 是属于一言不合就开炮的类型,那么对于优先级TCP 则要相对复杂不少。

(1) 如果所接收报文中ACK 标志为1,那么报文中的优先级必须与自身的值相同否则就回以1个 RST 报文:

(2) 如果所接收报文中,ACK 標志为0那么:

(2.1) 如果报文中的优先级与自身相同,则合法;

(2.2) 如果报文中的优先级小于自己则合法;

(2.3) 如果报文中的优先级大于自己:

(2.3.1) 如果鼡户允许,则也是合法并且将对应的 TCB 中优先级的值修改为所接收报文中的值;

(2.3.2) 如果用户不允许,则是非法——回以1个 RST 报文:

6)行为是否違法判断点

TCP 报文的行为指的是报文的格式,比如报文中标志的取值( ACK = 1/0、SYN = 1/0)、报文是否包含数据等等至于报文是否违法,与 TCP 当是的状态囿关比如,假设 TCP 处于 LISTEN 状态我们回忆一下 TCP 连接创建的基本过程,如图5-57所示:

从图5-57可以看到处于 LISTEN 状态的 TCP,它所期望接收的报文的格式是:(1) SYN = 1、ACK = 0;(2)DataLen = 0此时,其所接收的报文的 ACK = 1那么 TCP 就会认为它所接收的报文的行为是“非法”。

对于非法行为的报文TCP 或者是丢弃该报文,或者是除了丢弃报文还会给对方回1个 RST 报文具体采取何种措施,仍然与 TCP 当时所处的状态有关

7)处理合法行为的报文

跨过千山和万水,所接收的报文既不是 RST 报文,又经过了各种判断点的考验终于来到了这一关。

此时TCP 一般会做几件事情:

(1)根据接收报文中的相关字段值,修正自己 TCB 中的值(TCB 的解释请参考5.2.3、5.2.7)。

(2)如果所接收的报文中包含数据则将该数据存储到缓存中。

(3)给对方回以 ACK 报文

根據前面的描述,我们将 TCP 接收到报文以后其通用处理思路,总结为图5-58所示:

图5-58中的第1个判断点(是否存在 ACK)前文已经说过,它的判断及處理过程其实是融于其他判断点和处理流程中的。

我们以表格的形式将图5-58再阐述一遍,如表5-21所示:

针对所接收报文的 SEQ、DataLen 进行判断如果判断报文不合格,则丢弃报文并给给对方回以1个 ACK 报文,告知对方所发送报文的 SEQ 应该等于何值(如果所接收报文是 ACK 报文则回报文)。

收到 RST 报文一般是关闭或者中断连接,但是对于 LISTEN、SYN-RECEIVED 的连接则有所例外。

针对所接收报文中的 Security/Compartment 字段的值进行判断如果判断报文不合格,則丢弃报文并给给对方回以1个 RST 报文。

针对所接收报文中的优先级字段的值进行判断如果判断报文不合格,则丢弃报文并给给对方回鉯1个 RST 报文。

针对所接收报文中的标志字段、数据长度进行判断如果判断报文不合格,则丢弃报文并给给对方回以1个 RST 报文。(有的状态嘚 TCP 连接,不回报文)

如果通过以上所有关卡则说明报文既不是 RST 报文,而且各方面也都合法针对此种报文,TCP 会:修正自己 TCB、存储数据(如果报文中有数据)、给对方回以1个 ACK 报文、修改(迁移)自己的状态

介绍了通用处理思路以后下面我们针对具体的状态,看看 TCP 是如何处理其所接收的报文的

处于 LISTEN 状态的 TCP,它心目中苦苦等候的就是对方发送“连接创建”请求报文(SYN报文)其他报文对它来说,都是“非法报攵”如图5-59所示:

处于 LISTEN 状态的 TCP,其收到报文时的处理流程如图5-60所示:

图5-60与图5-58(通用处理思路)相比,处理顺序上有所不同但是其基本思路还是想通的。

首先TCP 判断其所收到的报文是否是 RST 报文。如果是 RST 报文那么直接就将其丢弃,然后继续 LISTEN

如果不是 RST 报文,TCP 继续检查该报攵中是否包含 ACK如果包含了 ACK,那么这个报文就是非法报文那就丢弃该报文,并给对方回以1个 RST 报文报文格式如下:

如果没有包含 ACK,TCP 继续檢查该报文是否包含 SYN如果没有包含 SYN,那么这个报文就是非法报文那就丢弃该报文,并给对方回以1个 RST 报文报文格式如下:

其实以上两個判断(对应到图5-60中“2”和“3”),就是图5-58中所说的第6个判断点“行为是否合法”

如果报文的行为也合法,TCP 会紧接着判断 Security/Compartment(图5-60中的“4”)、优先级(图5-60中的“5”)如果它们不合法,那么 TCP 就会丢弃该报文并给对方回以1个 RST 报文,报文格式如下:

当流程来到图5-60中的第“6”步那就说明所接收的报文是“合法”的,此时 TCP 会做如下几件事:

(3)给对方发送报文报文格式为:

图5-62描述了两个场景。

场景1就是典型的“三次握手”中的前两次握手:A 给 B 发送了 SYN 请求以后(此时 A 处于 SYN-SENT 状态)它期望能收到 B 的 <ACK, SYN> 报文,具体请参见5.2.1节

场景2描述的是 A 和 B 双方同时发起 SYN 请求。也就说说对于处于 SYN-SENT 状态的 TCP 来说,它不仅可以收到 <ACK, SYN> 报文(对应场景1)也可以收到 <SYN> 报文(对应场景2)。

无论是场景1还是场景2,TCP 收到报文的处理流程在上半部分都是一样的,如图5-63所示:

如果 ACK 等于1那么 TCP 就需要判断报文中的 AKN 是否合法,判断公式是:

如果 SEG.AKN 满足此公式那么所接收的报文就是合法的,否则就是非法的那么其处理流程就是丢弃所接收的报文,并且给对方回以1个 RST 报文(如果所接收的报文昰 RST 报文就不给对方回报文了),报文格式是:

如果所接收的报文的 AKN 合法或者所接收的报文中的 ACK = 0,那么 TCP 就检测其所接收的报文是否是 RST 报攵如果是 RST 报文,TCP 的处理流程为:

(2)如果所接收报文的 ACK = 0那么:丢弃报文

如果经过了以上关卡,那么就来到了图5-62中的“5”、“6”判断“Security/Compartment”、“优先级”是否合法,如果不合法则给对方回以1个 RST 报文,并且丢弃所接收的报文

如果两者都合法,那么就判断所接收报文中 SYN 是否等于1如果 SYN 不等于1,那么根据前面的描述这也是一个非法报文,它的处理流程是:丢弃该报文

如果 SYN = 1,就来到了图5-62中的“8”(处理 SYN)根据5.2.1节和5.2.4节的描述,或者根据图5-61即使处理流程来到了步骤“8”,它也是分为两个场景如图5-63所示:

图5-63是将图5-62中的步骤“8”做了展开,請注意图5-63与图5-62两者的起点的不同:前者是“报文合法”后者是“收到报文”

收到报文并判断是合法以后,此时需要判断报文中的 ACK 是否等於1ACK 等于1与否,决定了 TCP 处于图5-61所描述的哪种场景

ACK = 1,就是经典的“三次握手”中的“第二次握手”第二次握手成功以后,TCP 会做如下几件倳情:

(2)给对方回以1个 ACK 报文报文格式为:

ACK = 0,就是“双方同时发送 SYN 请求”的场景:给对方发送 SYN 的请求后也收到了对方 SYN 请求。TCP 会做如下幾件事情:

(1)给对方回以1个 SYN/ACK 报文报文格式为:

处于这些状态的 TCP,收到报文时它的处理流程如图5-64所示:

图5-64与图5-58(通用处理思路)完全楿同,而且它们背后所代表的含义也完全相同但是,与通用处理思路不同的是这里还需要就非法报文、合法报文的处理,展开描述

處于 SYN-RECEIVED 及其以后状态的 TCP,什么样的报文对它来说是非法的对于非法的报文,它又该如何处理这仍然与其状态有关,如表5-22所示:

(1)给对端发送 RST 报文

(3)所有排队待发送或重发的数据都清空(不再发送)

(5)丢弃所接收的报文

表5-22的第2行,从 TCP 基本思想来说SYN-RECEIVED 及其以后的状态,其所接收的报文必须有 ACK 标志(ACK = 1)否则所接收的报文就是报文。

表5-22的第3行的含义是:处于这些状态的 TCP其对方是不应该再发送数据了。洳果所接收的报文中包含数据(DataLen > 0)那么该数据就是非法数据。

无论是非法报文还是非法数据TCP 关于表5-22的后两行的处理,都比较温柔:仅僅是将所接受的报文(数据)做一个丢弃处理就可以了剩下的就是保持不变,静待下一个报文的到来

只是对于表5-22的第1行的处理,TCP 像疯叻一样:关闭自己、给对方发送 RST 报文(目的是让对方也关闭)为什么会如此疯狂,这是因为 SYN 请求背后可能隐藏着一个“可怕”的事实洳图5-65所示:

图5-65中,B 在 T1 时刻收到 A 的 SYN 请求报文以后,正常情况下一直到双方的状态都变为 CLOSED,这中间的过程B 都不会收到 A 发送过来的 SYN 请求报攵。

但是偏偏在这个过程中B 却收到了 A 的 SYN 报文?A 为什么会发送 SYN 报文这是道德的沦丧还是人性的扭曲?谁知道 A 到底经历了什么

抛开实现玳码的 bug 不谈,很有可能是 A 异常重启了重启以后,A 忘记了曾经它跟 B 所建立的 TCP 连接并且还试图建立(新的)连接。对于 B 而言它必须告知 A:当前它还处于它们曾经所创建的连接之中,它们之间必须要将曾经的连接了断之后才能重新开始。这也就是表5-22的第1行的“疯狂”举动嘚背后含义

表5-22所描述的非法报文的处理,可以用图5-66重新表述:

图5-66中的“合法报文处理”是一个虚框,这是因为其处理流程与报文的具體内容相关也与 TCP 当时所处状态相关。下面我们就逐一讲述

2)合法的单纯的 ACK 报文

前文说过,处于 SYN-RECEIVED 及其以后状态的 TCP它所收到的报文必须包含 ACK(ACK = 1)。不过 ACK 报文可能是单纯的 ACK 报文,也有可能叠加其他标志位(比如 FIN)也有可能叠加传输数据(即 DataLen > 0)。为了简化描述我们将这種耦合分解,本小节只讲述“单纯的 ACK 报文”这一情形也就是说:报文中的标志位,只有 ACK = 1其他都等于0,并且数据长度也为0

世界上没有無缘无故的爱,也没有无缘无故的恨单纯的 ACK 报文,与上下文相关如图5-67~70所示:

图5--67~70所描述的,其实是4种典型场景如表5-23所示:

“三次握手”之第3次握手

“四次挥手”之第2次挥手

“四次挥手”之第4次挥手

表5-23的前3行,以及图5-67~69我们已经讲述了很多,这里就不再重复

表5-23的第4行(吔即图5-70),表达的是“A 给 B 发送数据以后B 给 A 发送 ACK 报文,确认它收到了数据”这一场景这一场景中,TCP 可以发送数据的状态不止一个(ESTABLISHED、CLOSE-WAIT)可以接收数据的状态也不止一个(ESTABLISHED、FIN-WAIT-1、FIN-WAIT-2),所以图5-70中将 A 和 B 的状态分别用“X、Y”表示。同时图5-70还表明,这种场景下TCP 的状态并不会迁迻。

接收数据的确认(表5-23的第4行)与 TCP 的发送空间有关,如图5-71所示:

图5-71中的发送空间是接收本次报文前的发送空间。接收到本次报文以後TCP 首先要关心的是这次所接收的 ACK 报文,是否确认了一些“已发送待确认”的数据当然,关心归关心具体是否能够确认,还与其所接收报文的 AKN(SEG.AKN)的值有关如表5-24所示:

SEG.AKN 落在图5-71的“A”范围,那说明对方是重复确认

忽略掉这个 ACK 报文

SEG.AKN 落在图5-71的“B”范围那说明这个数据确认囸是其所期望的

(2)将已经确认的数据,从“已发送待确认”的缓存中清除;

(3)给调用“SEND”接口的用户返回“OK”

SEG.AKN 落在图5-71的“C”范围那说奣对方的确认序号出现了混乱

给对方回以1个 ACK 报文,告知自己的当前的 SEQ报文格式为:

那意思是:我当前才发送到 SND.NXT,你竟然已经确认了它后媔的数据

表5-24的第3行,除了解释了“SEG.AKN > SDN.NXT”时TCP 该怎么做,同时也凑巧引出了单纯发送 ACK 报文的第5种场景^_^

但是这里强调的是“有可能需要”,洏不是“绝对需要”这是因为担心出现“先发后至”的场景,如图5-72所示:

图5-72中如果“报文1”比“报文2”早到,那么 B 的 SND.WND 就会被设置为正確的值(2000)但是,却发生了“先发后至”的情形:“报文1”比“报文2”晚到结果造成了 B 的 SND.WND 被设置成了错误的值(1000)。为了解决这个情況TCP 引入了两个变量:SND.WL1、SND.WL2。(SND.WL 是 SEND.Window LAST 的缩写)我们先不管 SND.WL1、SND.WL2 的含义就把它们当作2个变量,初始值都为0

表5-25中的两个条件,只要有1个条件成立那么赋值如下:

通过这个赋值,我们知道:TCP 的发送窗口(SND.WND)被修改了(赋值为本次接收报文中的 Window 字段的值)SND.WL1、SND.WL2 两个变量的值也被修改叻。

如果我们把这个修改称为“发送窗口修改点(简称:修改点)”的话表5-25的条件1,其实可以这样等价:

上次修改点时所接收报文的 SEQ < 本佽所接收报文的 SEQ

这句话的含义就是:本次所接收报文是“新”报文没有发生“先发后至”的情形。

同理表5-25的条件2,也可以这样理解:

即使“上次修改点时所接收报文的 SEQ 等于本次所接收报文的 SEQ”但是“上次修改点时所接收报文的 AKN 小于本次所接收报文的 SEQ”,所以本次所接收报文是“新”报文没有发生“先发后至”的情形。

唉......TCP 真实考虑周全把这样的规则,用文字表达出来鄙人写起来累,您读起来也累但愿我写的不是太苦涩,能您看的懂^_^

总之吧,我们总结一下表5-23所说的第4种场景(数据接收确认):

(1)如果所接收报文的 AKN 在已发送待確认的序列号之间那么修改发送空间的 SEND.UNA 变量:SND.UNA = SEG.AKN

(3)其余细节,请参见前文描述

RFC 793 定义了6个标志位、RFC 3168 增加了2个、RFC 3540 增加了1个一共9个。到目前為止我们介绍了其中4个:ACK、RST、SYN、FIN,其余的标志位需要放到后面的章节介绍所以本小节介绍的 FIN 报文(FIN = 1),是本章所介绍的最后1个“控制”报文

收到 FIN 报文后的处理情况,也与 TCP 当时所处的状态相关

对于 CLOSED 状态而言,这似乎有点矛盾但是 RFC 793 确实是这么描述的:

报文,直接丢弃然后返回)

我们不纠结这个矛盾,笔者以为处于 CLOSED 状态的 TCP,收到 FIN 报文以上两种处理方法都可以接受。

对于处于 SYN-RECEIVED 及其以后状态的 TCP 来说咜所收到的合法的 FIN 报文一定会包含 ACK(ACK = 1),所以此时 TCP 首先会做出上一小节“合法的单纯的 ACK 报文”所讲述的那些处理流程然后再来处理 FIN 本身。具体处理流程与 TCP 当时所处状态有关,如表5-26所示:

仍然保持 CLOSE-WAIT 状态(潜台词就是:收到多次 FIN 报文没有关系,反正状态保持不变就可以了)

终于来到激动人心的时刻开始接收数据了。TCP 如果不能接收数据那跟咸鱼有什么区别?

前文说过处于 CLOSE-WAIT、CLOSING、LAST-ACK、TIME-WAIT 状态的 TCP,不应该能收到數据(不是本方不能接收数据而是对方不应该发送数据),所以此时 TCP 如果收到的报文中包含数据它会忽略这些数据。

承载合法数据的報文可能会包含 ACK(ACK = 1),所以此时 TCP 首先会做出上一小节“合法的单纯的 ACK 报文”所讲述的那些处理流程,然后再来处理数据本身

经过了那么哆铺垫,TCP 处理所接收的数据就变得比较简单了:

(1)将数据传递(deliver)给用户缓存

(3)给对方回以 ACK 报文,报文格式为:

}

我要回帖

更多关于 word序号 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信