5.8 TCP的运输连接管理
# 5.8 TCP的运输连接管理
从本节课开始,我们将分两次课来介绍TCP的运输连接管理
# 5.8.1 TCP的连接建立
TCP是面向连接的协议,它基于运输连接来传送TCP报文段,
TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。
TCP运输连接有以下三个阶段,
- 第一个阶段是建立TCP连接,也就是通过三报文握手来建立TCP连接。
- 第二个阶段是数据传送,也就是基于已建立的TCP连接,进行可靠的数据传输。
- 第三个阶段是释放连接,也就是在数据传输结束后,还要通过四报文挥手来释放TCP连接,
TCP的运输连接管理就是使运输连接的建立和释放都能正常的进行。
本节课我们介绍TCP连接的建立过程,TCP的连接建立要解决以下三个问题,
第一使TCP双方能够确知对方的存在,
第二使TCP双方能够协商一些参数,例如最大窗口值是否使用窗口扩大选项和时间戳选项以及服务质量等。
第三使TCP双方能够对运输实体资源,例如缓存大小,连接表中的项目等进行分配。
接下来我们就来看看TCP使用三报文握手建立连接的具体过程。这是两台要基于TCP进行通信的主机,其中一台主机中的某个应用进程,主动发起TCP连接,建立称为TCP客户。另一台主机装被动等待TCP连接建立的应用进程,称为TCP服务器。我们可以将TCP建立连接的过程比喻为握手,握手需要在TCP客户和服务器之间交换三个TCP报文段
最初两端的TCP进程都处于关闭状态,一开始 TCP服务器进程首先创建传输控制块,用来存储TCP连接中的一些重要信息,例如 TCP连接表,指向发送和接收缓存的指针,指向重传队列的指针,当前发送和接收序号等。之后就要准备接受TCP客户进程的连接请求。此时TCP服务器进程就要进入监听状态,等待TCP客户进程的连接请求。TCP服务器进程是被动等待来自TCP客户进程的连接请求,而不是主动发起,因此称为被动打开连接。
- TCP客户进程也是首先创建传输控制块,然后在打算建立TCP连接时,向TCP服务器进程发送TCP连接请求报文段,并进入同步已发送状态。TCP连接请求报文段首部中的同步位SYN被设置为1,表明这是一个TCP连接请求报文段,序号字段SEQ被设置了一个初始值X,作为TCP客户进程所选择的初始序号。请注意TCP规定,SYN被设置为1的报文段,不能携带数据,但要消耗掉一个序号。由于TCP连接建立是由TCP客户进程主动发起的,因此称为主动打开连接。
- TCP服务器进程收到TCP连接请求报文段后。如果同意建立连接,则向TCP客户进程发送TCP连接请求确认报文段,并进入同步已接收状态。该报文段首部中的同部位SYN和确认位ACK都设置为1,表明这是一个TCP连接请求确认报文段。序号字段SEQ被设置了一个初始值Y,作为TCP服务器进程所选择的初始序号,确认号字段ACK的值被设置成了X+1,这是对TCP客户进程所选择的初始序号的确认。请注意这报文段也不能携带数据,因为它是SYN被设置为1的报文段,但同样要消耗掉一个序号
- TCP客户进程收到TCP连接请求确认报文段后,还要向TCP服务器进程发送一个普通的TCP确认报文段,并进入连接已建立状态。该报文段首部中的确认为ACK被设置为1,表明这是一个普通的TCP确认报文段,序号字段SEQ被设置为X+1,这是因为 TCP客户进程发送的第一个TCP报文段的序号为X并且不携带数据,因此第二个报文段的序号为X+1。请注意TCP规定,普通的TCP确认报文段可以携带数据,但如果不携带数据则不消耗序号。在这种情况下,所发送的下一个数据报文段的序号仍是X+1,确认号字段ACK被设置为Y+1,这是对TCP服务器进程所选择的初始序号的确认。
TCP服务器进程收到该确认报文段后也进入连接已建立状态。现在TCP双方都进入了连接已建立状态,他们可以基于已建立好的TCP连接进行可靠的数据传输了。
请同学们思考这样一个问题,为什么TCP客户进程最后还要发送一个普通的TCP确认报文段,这是否多余?换句话说,能否使用两报文握手建立连接答案是并不多余,不能简化为两报文握手。我们来举例说明,考虑这样一种情况,TCP客户进程发出一个TCP连接请求报文段,但该报文段在某些网络节点长时间滞留了,这必然会造成该报文段的超时重传。假设重传的报文段在TCP服务器进程正常接收,TCP服务器进程给TCP客户进程发送一个TCP连接,请求确认报文段,并进入连接已建立状态。请注意,由于我们改为两报文握手,因此TCP服务器进程发送完TCP连接请求确认报文段后进入的是连接已建立状态,而不像三报文握手那样进入同步已接收状态,并等待TCP客户进程发来,针对TCP连接请求确认报文段的普通确认报文段,TCP客户进程收到TCP连接,请求确认报文段后,进入TCP连接已建立状态,但不会给TCP服务器进程发送针对该报文段的普通确认报文段,现在 TCP双方都处于连接已建立状态,他们可以相互传输数据之后可以通过四报文挥手来释放连接,TCP双方都进入了关闭状态,
一段时间后之前滞留在网络中的失效的TCP连接请求报文段到达了TCP服务器进程,TCP服务器进程会误认为这是TCP客户进程,又发起了一个新的TCP连接请求,于是给TCP客户进程发送TCP连接请求,确认报文段,并进入连接已建立状态。该报文段到达TCP客户进程,由于TCP客户进程并没有发起新的TCP连接请求,并且处于关闭状态,因此不会理会该报文段,但TCP服务器进程已进入了连接已建立状态,他认为新的TCP连接已建立好了,并一直等待TCP客户进程发来数据,这将白白浪费TCP服务器进程所在主机的很多资源。
练习题,这是计算机专业考研全国统考计算机网络部分2011年的题39,答案是选项C 如图所示,这是本节课所介绍的TCP通过三报文握手建立连接的过程。根据题意,主机甲中的是TCP客户进程,主机乙中的是TCP服务器进程,这是主机甲中TCP客户进程,像主机乙中TCP服务器进程发送的第一个TCP段,其首部中的同部位SYN的值为1,序号字段SEQ的值就是题目所给的11220,这是主机乙中TCP服务器进程,给主机假装TCP客户进程发送的TCP连接请求确认报文段,其首部中的同步位SYN和确认位ACK的值都被设置为1,表明这是一个TCP连接请求确认报文段,确认号字段ACK的值是对主机甲中TCP客户进程多选择初始序号,11220的确认,因此为11221至此我们就已经可以选出正确答案为选项C了。序号字段SEQ的值是主机乙装TCP服务器进程所选择的初始序号,可由TCP服务器进程随意指定,与其他报文段中的值无关。在本题的正确选项C中,序号字段SEQ的值恰好与确认号字段ACK的值同为11221,这正是本题迷惑大家的地方,使很多同学认为该选项有点别扭。
本节课的内容小结如下
# 5.8.2 TCP的连接释放
本节课我们介绍TCP的连接释放,TCP通过四报文挥手来释放连接。我们来举例说明,数据传输结束后,TCP通信双方都可以释放连接,现在TCP客户进程和TCP服务器进程都处于连接已建立状态。假设使用TCP客户进程的应用进程,通知其主动关闭TCP连接,TCP客户进程会发送TCP连接释放报文段,并进入终止等待一状态。该报文段首部中的终止位FIN和确认为ACK的值都被设置为1,表明这是一个TCP连接释放报文段,
同时也对之前收到的报文段进行确认。序号SEQ字段的值设置为U它等于TCP客户进程之前已传送过的数据的最后一个字节的序号加一。
请注意TCP规定终止为FIN等于一的报文段,即使不携带数据也要消耗掉一个序号,确认号ESSAY字段的值设置为v,它等于TCP客户进程之前已收到的数据的最后一个字节的序号加一,TCP服务器进程收到TCP连接释放报文段后,会发送一个普通的TCP确认报文段,并进入关闭等待状态。该报文段首部中的确认为ACK的值,被设置为一,表明这是一个普通的TCP确认报文段,序号SEQ字段的值设置为V,它等于TCP服务器进程之前以传送过的数据的最后一个字节的序号加1,这也与之前收到的TCP连接释放报文段中的确认号匹配,确认号ACK字段的值设置为U+1,这是对TCP连接释放报文段的确认。
TCP服务器进程这时应通知高层应用进程,TCP客户进程要断开与自己的TCP连接,此时从TCP客户进程到TCP服务器进程,这个方向的连接就释放了,这时的TCP连接属于半关闭状态,也就是TCP客户进程已经没有数据要发送了,但TCP服务器进程如果还有数据要发送,TCP客户进程仍要接收,也就是说从TCP服务器进程到TCP客户进程,这个方向的连接并未关闭,这个状态可能会持续一段时间,TCP客户进程收到TCP确认报文段后,就进入终止等待二状态,等待TCP服务器进程发出的TCP连接释放报文段。
若使用TCP服务器进程的应用进程已经没有数据要发送了,应用进程就要通知其TCP服务器进程释放连接。由于TCP连接释放是由TCP客户进程主动发起的,因此TCP服务器进程对TCP连接的释放称为被动关闭连接,TCP服务器进程发送TCP连接释放报文段,并进入最后确认状态。该报文段首部中的终止为FIN和确认为ACK的值,都被设置为1,表明这是一个TCP连接释放报文段,同时也对之前收到的报文段进行确认。现在假定序号SEQ字段的值为W,这是因为在半关闭状态下,TCP服务器进程可能又发送了一些数据,确认号ACK字段的值为U+1,这是对之前收到的TCP连接释放报文段的重复确认。TCP客户进程收到TCP连接释放报文段后,必须针对该报文段发送普通的TCP确认报文段,之后进入时间等待状态,该报文段首部中的确认为ACK的值,被设置为1,表明这是一个普通的TCP确认报文段,序号SEQ字段的值设置为U+1,这是因为TCP客户进程之前发送的TCP连接释放报文段,虽然不携带数据,但要消耗掉一个序号,确认号ACK字段的值设置为W+1,这是对所收到的TCP连接释放报文段的确认。TCP服务器进程收到该报文段后就要进入关闭状态,而TCP客户进程还要经过两倍的MSL后才能进入关闭状态。MSL的意思是最长报文段寿命,RFC793文档建议为两分钟,
也就是说 TCP客户进程进入时间等待状态后,还要经过4分钟才能进入关闭状态,这完全是从工程上来考虑的。对于现在的网络MSL取为两分钟可能太长了,因此TCP允许不同的实现和根据具体情况使用更小的MSL值。
那么 TCP客户进程在发送完最后一个确认报文段后,为什么不直接进入关闭状态,而是要进入时间等待状态,两倍MSL后才进入关闭状态,这是否有必要呢?来看这种情况,TCP服务器进程发送TCP连接释放报文段后进入最后确认状态,TCP客户进程收到该报文段后,发送普通的TCP确认报文段,并进入关闭状态,而不是时间等待状态。然而该TCP确认报文段丢失了,这必然会造成TCP服务器进程,对之前所发送的TCP连接释放报文段的超时重传,并仍处于最后确认状态。重传的TCP连接释放报文段到达TCP客户进程,由于TCP客户进程属于关闭状态,因此不理睬该报文段,这必然会造成 TCP服务器进程反复重传TCP连接释放报文段,并一直处于最后确认状态,而无法进入关闭状态。
因此时间等待状态以及处于该状态两倍MSL的时长,可以确保TCP服务器进程可以收到最后一个TCP确认报文段而进入关闭状态。另外TCP客户进程在发送完最后一个TCP确认报文段后,再经过两倍MSL时长,就可以使本次连接持续时间内所产生的所有报文段都从网络中消失,这样就可以使下一个新的TCP连接中不会出现旧连接中的报文段。以上就是TCP通过4报文挥手释放连接的过程。
最后我们再来看看TCP中饱和计时器的作用。设想这样一种情况,TCP双方已经建立了连接,后来TCP客户进程所在的主机突然出现了故障,显然 TCP服务器进程以后就不能再收到TCP客户进程发来的数据,因此应当有措施使TCP服务器进程,不要再白白等待下去。换句话说,TCP服务器进程应该如何发现这种情况?方法就是使用保活计时器、TCP服务器进程每收到一次TCP客户进程的数据,就要重新设置并启动保活计时器,若保活计时器定时周期内未收到TCP客户进程发来的数据,则当保活计时器到时后,TCP服务器进程就向TCP客户进程发送一个探测报文段,以后每隔75秒钟发送一次,若一连发送10个探测报文段,后仍无TCP客户进程的响应,TCP服务器进程就认为TCP客户进程所在主机出了故障,接着就要关闭这个连接
本节课的内容小结如下