一、TCP的传输连接管理的三个阶段
IP协议的作用范围:提供主机之间的逻辑通信
TCP和UDP协议的作用范围:提供进程之间的逻辑通信
TCP (Transmission Control Protocol) 传输控制协议
UDP (User Datagram Protocol ) 用户数据报协议
当运输层采用面向连接的TCP协议时,尽管下面的网络是不可靠的(只提供尽最大努力服务),但这种逻辑通信信道就相当于一条全双工的可靠信道。
当运输层采用无连接的UDP协议时,这种逻辑通信信道是一条不可靠信道
1、TCP连接的建立都是采用客户端/服务器方式
主动发起连接建立的应用进程叫做客户端(client)。
被动等待连接建立的应用进程叫做服务器(server)。
传输连接就有三个阶段,即:连接建立、数据传送和连接释放。
传输连接的管理就是使传输连接的建立和释放都能正常地进行。
2、连接建立过程中要解决以下三个问题
要使每一方能够确知对方的存在
要允许双方协商一些参数(如最大报文段长度,最大窗口大小,服务质量等)。
能够对运输实体资源(如缓存大小,连接表中的项目等)进行分配。
3、TCP连接的状态转移
4、TCP的三次握手建立传输连接
TCP的状态 (SYN, FIN, ACK, PSH, RST, URG)
在TCP层,有个FLAGS字段,这个字段有以下几个标识:
SYN synchronous 建立联机
ACK acknowledgement 确认
PSH push 传送
FIN finish 结束
RST reset 重置
URG urgent 紧急
Sequence number 顺序号码
acknowledge number 确认号码
其中,对于我们日常的分析有用的就是前面的五个字段。
第一次握手:主机A向B发出连接请求报文段
其首部中发送位码为:同步位为SYN=1,并随机产生序号seq=x,表明传送数据时的第一个数据字节的序号是x;并进入SYN_SEND状态,等待服务器确认;
第二次握手:主机B收到连接请求报文段后(主机B由SYN=1知道,A要求建立联机),如同意,则发回确认;
B在确认报文段中应使SYN=1,ACK=1,其确认号ack=x+1,自己选择的序号seq=y的包;此时服务器进入SYN_RECV状态;
第三次握手:主机A收到此报文段后B给出确认,
B在确认报文段中使用ACK=1,确认号ack=y+1,序号为seq=x+1
A的TCP通知上层应用进程,连接已经建立
B的TCP收到主机A的确认后,也通知其上层应用进程;TCP连接已经建立
5、TCP的4次挥手释放传输连接
第一次挥手:数据传输结束后,通信的双方都可释放连接
现在A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭 TCP连接。
A把连接释放报文段首部的FIN = 1,其序号seq = u,等待B的确认。
第二次挥手:B发出确认
确认报文段中,ACK=1,确认号ack = u +1,而这个报文段自己的序号 seq = v。
TCP服务器进程通知高层应用进程,从A到B这个方向的连接就释放了,TCP连接处于半关闭状态;
B若发送数据,A仍要接收。
第三次挥手:若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接
在确认报文段中 FIN=1,ACK= 1,确认号ack=u +1,自己的序号seq=w;
第四次挥手: A收到连接释放报文段后,必须发出确认
在确认报文段中 ACK=1,确认号ack=w+1,自己的序号 seq =u+1。
二、常问问题
1、为什么建立连接协议是三次握手,而关闭连接却是四次挥手呢?
这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的。
2、为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态?
MSL 报文最大生存时间,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃
这是因为虽然双方都同意关闭连接了,而且挥手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的ACK报文。
3、为什么不能用两次握手进行连接?
我们知道,3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
如果把三次握手改成仅需要两次握手,死锁是可能发生的。
作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。