TCP的运输连接管理
一、TCP建立连接
1. 简单介绍
-
TCP是面向连接的协议,它基于运输连接来传输TCP报文段。
-
TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。
-
TCP运输连接有以下三个阶段。
建立TCP连接 数据传送 释放TCP连接
- TCP的运输连接管理就是使运输连接的建立和释放都能正常的进行。
2. TCP的连接建立需要解决的问题
- 使TCP双方能够确知对方的存在。
- 使TCP双方能够协商一些参数(如最大窗口值、是否使用窗口扩大选项)。
- 使TCP双方能够对运输实体资源(如缓冲大小、连接表中的项目等)进行分配。
3. 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双方都进入了连接已建立状态。
4. 能否使用“两报文握手”建立连接。
-
不能简化为“两报文握手”。
-
如果发送以下这种情况。TCP客户进程发出一个TCP连接请求报文段,但因为某种原因在网络中滞留了,则会造成超时重传。
-
假设重传的报文段被服务器正常接收。
-
数据传输结束后双方都进入关闭状态,一段时候后之前滞留在网络中的那个失效的TCP连接请求报文段到达TCP服务器进程,TCP服务器进程会误认为这是TCP客户进程又发起了一个新的TCP连接请求,于是给TCP客户进程发送TCP连接请求确认报文段,并进入连接已建立状态。
-
该报文段到达TCP客户进程,由于TCP客户进程并没有发起新的TCP连接请求,并且处于关闭状态,因此不会理会该报文段。但TCP服务器进程已进入连接已建立状态,它认为新的TCP连接已经建立好了,并一直等待TCP客户进程发来数据,这样将会浪费TCP所在服务器的很多资源。
-
所以使用“三报文握手”而不是“两报文握手”是为了防止已失效的连接请求报文段突然又传送到了TCP服务器,因而导致错误。
二、TCP的连接释放
1. TCP通过“四报文挥手”来释放连接
- TCP通信双方都可以释放连接,现在TCP客户进程和TCP服务器进程都处于连接已建立状态。假设使用TCP客户进程的应用进程通知其主动关闭TCP连接。
① 第一次“挥手”
-
TCP客户进程会发送TCP连接释放报文段,并进入终止等待1状态。
-
该报文段首部中的终止位FIN和确认位ACK的值都被设置为1,表明这个一个TCP连接释放报文段,同时也对之前收到的报文段进行确认。
-
序号位seq字段的值设置为u,它等于TCP客户进程之前已传送过的数据的最后一个字节的序号加1。
TCP规范终止位FIN等于1的报文段即使不携带数据, 也要消耗掉一个序号。
-
确认号ack字段的值设置为v,它等于TCP客户进程之前已收到的数据的最后一个字节的序号加1。
② 第二次“挥手”
-
TCP服务器进程收到TCP连接释放报文段后,会发送一个普通的TCP确认报文段并进入关闭等待状态。
-
该报文段首部中的确认位ACK的值被设置为1,表明这个一个普通的TCP确认报文段。序号seq的值被设置为v,它等于TCP服务器进程之前已传送过的数据的最后一个字节的序号加1,这也与之前收到的TCP连接释放报文段中的确认号匹配。
-
确认号ack的值设置为u+1,这是对TCP连接释放报文段的确认。
-
此时,从TCP客户进程到TCP服务器进程这个方向的连接就释放了。这时的TCP连接属于半关闭状态,也就是TCP客户进程没有数据要发送了,但TCP服务器进程如果还有数据要发送,TCP客户进程仍要接收。从TCP服务器进程到TCP客户进程这个方向的连接并未关闭。这个状态可能会持续一段时间。
③ 第三次“挥手”
- TCP客户进程收到TCP确认报文段后就进入终止等待2状态,等待TCP服务器进程发出TCP连接释放报文段。
- 若使用TCP服务器进程的应用进程已经没有数据要发送了,应用进程就通知其TCP服务器进程释放连接。由于TCP连接释放是由TCP客户进程主动发起的,因此TCP服务器进程对TCP连接的释放称为被动关闭连接。
- TCP服务器进程发送TCP连接释放报文段并进入最后确认状态。
- 该报文段首部中的终止位FIN和确认位ACK的值都被设置为1,表明这是一个TCP连接释放报文段,同时也是对之前收到的报文段进行确认。现在假定序号seq字段的值为w,这是因为在关闭状态下,TCP服务器进程可能又发送了一些数据。
- 确认号ack字段的值为u+1,这是对之前收到的连接释放报文段的重复确认。
④ 第四次“挥手”
-
TCP客户进程收到TCP连接释放报文段后,必须针对该报文段发送不同的TCP确认报文段,之后进入时间等待状态。
-
该报文段首部中的确认位ACK的值被设置为1,表明这是一个普通的TCP确认段。序号seq的值设置为u+1,这是因为TCP客户进程之前发送的TCP连接释放报文段虽然不携带数据,但要消耗掉一个序号。
-
确认号ack字段的值设置为w+1,这是对所收到的TCP连接释放报文段的确认。
-
TCP服务器进程收到该报文段后就进入关闭状态。
-
TCP客户进程还有经过2MSL后才能进入关闭状态。
MSL意思是最长报文段寿命,RFC793建议为2分钟。
2. 等于2MSL是否有必要。
-
如果出现这种情况,TCP服务器进程发送TCP连接释放报文段后进入最后确认状态。TCP客户进程收到该报文段后,发送普通的TCP确认报文段,并进入关闭状态而不是时间等待状态。然后该TCP确认报文段丢失了。
-
这必然会造成TCP服务器进程,对之前所发送的TCP连接释放报文段的超时重传,并仍处于最后确认状态。
-
重传的TCP连接释放报文段到达TCP客户进程,由于TCP客户进程处于关闭状态,因此不理睬该报文段,这必然会造成TCP服务器进程反复重传TCP连接释放报文段,并一直处于最后确认状态而无法进入关闭状态。