TCP 是面向连接的协议。运输连接是用来传送 TCP 报文的。运输连接有三个阶段,即:连接建立、数据传送和连接释放。运输连接的管理是使运输连接的建立和释放都能正常地进行。
在 TCP 连接建立过程中要解决三个问题:
TCP 连接的建立采用 C/S 方式。主动发起连接建立的应用进程叫做客户 (client),被动等待连接建立的应用进程叫做服务器 (server)。
TCP 连接建立的过程叫做握手,握手需要在客户和服务器之间交换三个 TCP 报文段。下图画出了三报文握手 (three way (three message) handshake) [RFC 973] 建立 TCP 连接的过程。
上面给出的连接建立过程叫做三报文握手。
注意,在图 5-28 中 B 发送给 A 的报文段,也可拆成两个报文段。可以先发送一个确认报文段 (ACK = 1,ack = x + 1),然后再发送一个同步报文段 (SYN = 1,seq = y)。这样的过程就变成了四报文握手,但效果是一样的。
上述的 TCP 连接释放过程是四报文握手。
为什么 A 在 TIME-WAIT 状态必须等待 2MSL 的时间呢?
TCP 还设有一个保活计时器 (keepalive timer)。假设客户已与服务器建立了 TCP 连接,但客户端主机突然出故障。服务器不能再收到此客户发来的数据。
可以使用保活计时器使服务器不要再等待。服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是两小时。若两小时没有收到客户数据,服务器就发送一个探测报文段,以后则每隔 75 秒发送一次,若一连发送 10 个探测报文段后仍无客户的响应,服务器就认为客户端出现了故障,接着就关闭这个连接。
上图中,粗实线箭头表示对客户进程的正常变迁,粗虚线箭头表示对服务器进程的正常变迁,另一种细线箭头表示异常变迁。
5-41 用 TCP 传送 512 字节的数据。设窗口为 100 字节,而 TCP 报文段每次也是传送 100 字节的数据。再设发送方和接收方的起始序号分别选为 100 和 200,试画出类似于图 5-28 的工作示意图。从连接建立阶段到连接释放都要画上。
解:发送方 A,接收方 B。
建立连接:
A->B:SYN = 1,seq = 100
B->A:SYN = 1,ACK = 1,seq = 200,ack = 101
A->B:ACK = 1,seq = 101,ack = 201
传送数据:
A->B:ACK = 1,seq = 101,ack = 201,DATA(100B)
B->A:ACK = 1,seq = 201,ack = 201,rwnd = 100
A->B:ACK = 1,seq = 201,ack = 201,DATA(100B)
B->A:ACK = 1,seq = 201,ack = 301,rwnd = 100
A->B:ACK = 1,seq = 301,ack = 201,DATA(100B)
B->A:ACK = 1,seq = 201,ack = 401,rwnd = 100
A->B:ACK = 1,seq = 401,ack = 201,DATA(100B)
B->A:ACK = 1,seq = 201,ack = 501,rwnd = 100
A->B:ACK = 1,seq = 501,ack = 201,DATA(100B)
B->A:ACK = 1,seq = 201,ack = 601,rwnd = 100
A->B:ACK = 1,seq = 601,ack = 201,DATA(12B)
B->A:ACK = 1,seq = 201,ack = 613,rwnd = 100
释放连接:
A->B:FIN = 1,ACK = 1,seq = 613,ack = 201
B->A:ACK = 1,seq = 201,ack = 614
B->A:FIN = 1,ACK = 1,seq = 201,ack = 614
A->B:ACK = 1,seq = 614,ack = 202
注意,SYN 报文段和 FIN 报文段即使不携带数据,也要消耗掉一个序号。ACK 报文段如果不携带数据,则不消耗序号。
5-42 在图 5-29 中所示的连接释放过程中,在 ESTABLISHED 状态下,服务器进程能否先不发送 ack = u + 1 的确认?(因为后面要发送的连接释放报文段中仍有 ack = u + 1 这一信息。)
解:如果 B 不再发送数据了,是可以把两个报文段合并成为一个,即只发送 FIN + ACK 报文段。
但如果 B 还有数据要发送,而且要发送一段时间,那就不行,因为 A 迟迟收不到确认,就会以为刚才发送的 FIN 报文段丢失了,就超时重传这个 FIN 报文段,浪费网络资源。
5-43 在图 5-30 中,在什么情况下会发生从状态 SYN_SENT 到状态 SYN_RCVD 的变迁?
解:当 A 和 B 都作为客户,即同时主动打开 TCP 连接。这时每一方的状态变迁都是:CLOSED->SYN-SENT->SYN-RCVD->ESTABLISHED
5-44 试以具体例子说明为什么一个运输连接可以有多种方式释放。可以设两个互相通信的用户分别连接在网络的两结点上。
解:设 A,B 建立了运输连接。
协议应考虑一下实际可能性:
A 或 B 故障,应设计超时机制,使对方退出,不至于死锁。
A 主动退出,B 被动退出。
B 主动退出,A 被动退出。
5-45 解释为什么突然释放运输连接就可能会丢失用户数据,而使用 TCP 的连接释放方法就可保证不丢失数据。
解:当主机 1 和主机 2 之间连接建立后,主机 1 发送了一个 TCP 报文段并正确抵达主机 2,接着主机 1 发送另一个 TCP 报文段,这次很不幸,主机 2 在收到第二个 TCP 数据段之前发出了释放连接请求,如果就这样突然释放连接,显然主机 1 发送的第二个 TCP 报文段会丢失。
而使用 TCP 的连接释放方法,主机 2 发出了释放连接的请求,那么即使收到主机 1 的确认后,只会释放主机 2 到主机 1 方向的连接,即主机 2 不再向主机 1 发送数据,而仍然可接收主机 1 发来的数据,所以可保证不丢失数据。
5-46 试用具体例子说明为什么在运输连接建立时要使用三次握手。说明如不这样做可能会出现什么情况。
★ \bigstar ★ 为什么 A 最后还要发送一次确认呢?这主要是为了防止已失效的连接请求报文段突然又传送到了 B,因而产生错误。
5-47 一个客户向服务器请求建立 TCP 连接。客户在 TCP 连接建立的三报文握手中的最后一个报文段中捎带上一些数据,请求服务器发送一个长度为 L 字节的文件。假定:
(1) 客户和服务器之间的数据传输速率是 R 字节/秒,客户与服务器之间的往返时间是 RTT (固定值)。
(2) 服务器发送的 TCP 报文段的长度都是 M 字节,而发送窗口大小是 nM 字节。
(3) 所有传送的报文段都不会出现差错 (无重传),客户收到服务器发来的报文段后就及时发送确认。
(4) 所有的协议首部开销都可忽略,所有确认报文段和连接建立阶段的报文段的长度都可忽略 (即忽略这些报文段的发送时间)。
试证明,从客户开始发起连接建立到接收服务器发送的整个文件多需的时间 T 是:
T = 2 RTT + L/R,当 nM > R (RTT) + M
或 T= 2 RTT + L/R + (K - 1)[M/R + RTT - nM/R],当 nM < R (RTT) + M
其中,K = ⌈ \lceil ⌈ L/nM ⌉ \rceil ⌉,符号 ⌈ x ⌉ \lceil x \rceil ⌈x⌉ 表示若 x x x 不是整数,则把 x x x 的整数部分加 1。
(提示:求证的第一个等式发生在发送窗口较大的情况,可以连续把文件发送完。求证的第二个等式发生在发送窗口较小的情况,发送几个报文段后就必须停顿下来,等收到确认后再继续发送。建议先画出双方交互的时间图,然后再进行推导。)
解:发送窗口的两种不同情况如下图所示。
图 (a):
M/R 是一个报文段的发送时间。
nM 是窗口大小,nM/R 是把窗口内的数据都发送完所需要的时间。
如果 nM/R > M/R + RTT ,那么服务器在发送窗口内的数据还没有发送完,就收到客户的确认,因此,服务器可以连续发送,直到全部数据发送完毕。
这个不等式两边都乘以 R,就得出等效的条件:
当 nM > R (RTT) + M 发送窗口内的数据还没有发送完就收到确认,因此,服务器可以连续发送,直到全部数据发送完毕。
因此,客户接收全部数据所需的时间是:
T = 2 RTT + L/R,当 nM > R(RTT) + M
图 (b):
当 nM > R (RTT) + M 时,服务器把发送窗口内的数据发送完毕时还收不到确认,因此必须停止发送。从图中可知,停止的时间间隔是 M/R + RTT - nM/R。
整个文件 L 要划分为 K = ⌈ \lceil ⌈L/nM ⌉ \rceil ⌉ 次传送,停止的时间间隔有 (K-1) 个。这样就证明了求证的公式:
T = 2 RTT + L/R + (K-1)[M/R + RTT - nM/R],当 nM < R (RTT) + M
5-62 TCP 连接处于 ESTABLISHED 状态。以下的事件相继发生:
(1) 收到一个 FIN 报文段。
(2) 应用程序发送“关闭”报文。
在每一个事件之后,连接的状态是什么?在每一个事件之后发生的动作是什么?
解:见图 5-30。
(1) 这是对服务器进程的正常变迁。当收到 FIN 时,服务器端向客户端发送 ACK 报文段,并进入到 CLOSE-WAIT 状态。
(2) 这是对服务器进程的正常变迁。服务器端应用程序发送“关闭”报文给服务器,表明没有数据要发送了。这时服务器就应当发送 FIN 报文段给客户,然后进入到 LAST-ACK 状态,并等待来自客户端的最后的确认。
5-63 TCP 连接处于 SYN-RCVD 状态。以下的事件相继发生:
(1) 应用程序发送“关闭”报文。
(2) 收到 FIN 报文段。
在每一个事件之后,连接的状态是什么?在每一个事件之后发生的动作是什么?
解:(1) 这是异常变迁。应用进程向对方发送 FIN 报文段,进入 FIN-WAIT-1 状态。
(2) 这是异常变迁。应用进程收到 FIN 报文段,向对方发送 ACK 报文段,进入 CLOSING 状态。
5-64 TCP 连接处于 FIN-WAIT-1 状态。以下的事件相继发生:
收到 ACK 报文段。
收到 FIN 报文段。
发生了超时。
在以上的每一个事件之后,连接的状态是什么?在每一个事件之后发生的动作是什么?
解:客户收到 ACK 报文段后,进入 FIN-WAIT-2 状态。
客户收到 FIN 报文段后,向对方发送 ACK 报文段,进入 TIME-WAIT 状态。
发生了超时,也就是等待 2MSL 时间后,客户进入 CLOSED 状态。
5-68 在 TCP 的连接建立的三报文握手过程中,为什么第三个报文段不需要对方的确认?这会不会出现问题?
A 发送的第二个报文段仅仅是 ACK 报文段,是个可以省略的报文段,即使丢失了也无妨,只要下面紧接着就可以发送数据报文段即可。
【计算机网络 (谢希仁) 习题题解】目录