TCP连接
一个TCP连接是由一对端点或套接字构成,其中通信的每一端都由一对(IP地址,端口号)所唯一标识。 一个TCP连接通常分为三个阶段:启动(三次握手)、数据传输、退出(四次挥手)。
三次握手
概览

- 第一步,客户端的TCP首先向服务器的TCP发送一个特殊的TCP报文段,该报文段不包含应用层的数据,但是报文段的首部中的一个标志位(即SYN比特)会被置为1,因此这个特殊报文段被称为SYN报文段。客户端会随机选择一个初始序号(J)并将此序号放置于该起始的TCP SYN报文段的序号字段里,整个报文字段会封装在一个IP数据报中并发给服务器。此时,客户端进入SYN-SENT状态。
- 第二步,一旦包含SYN报文段的IP数据报到达了服务器,服务器就会从数据报中提取出SYN报文段,为该TCP连接分配缓存和变量,并向客户端发送允许连接的报文段(ACK(J + 1)),该报文段也不包含应用层数据。与此同时服务器也随机选择一个初始序号(K)并将此序号放置于TCP报文段首部的序号字段中,即(SYN(K)),随确认字段ACK一并发送给客户端。此报文字段通常被称为SYNACK报文段,此时服务器进入SYN-RECEIVED状态。
- 第三步,客户端接收到SYNACK报文段,为该连接分配缓存和变量,此时客户端进入ESTABLISHED状态。客户端向服务器发送另外一个报文段,这个报文段是对服务器的允许连接的报文段的确认(ACK(K + 1)),与前两次不同,这次报文段中可携带应用层数据,由于连接已经建立,SYN比特被置为0。服务器收到这个报文段后,也进入ESTABISHED状态。 完成这三个步骤后,客户端和服务器的每一个报文段中都可以携带应用层的数据,且SYN比特都将被置为0。建立TCP连接的三个步骤也被称为TCP三次握手。 三次握手的目的不仅在于让通信双方了解一个连接正在建立, 还在于利用数据包的选项来承载特殊的信息,交换初始序列号。-------《TCP/IP 详解 卷1:协议》
为什么是三次握手?为什么不是两次握手?
三次握手: A---->B: [A: I'm A.]
B---->A: [B: Hello A, I'm B.]
A---->B: [A: Hello B, nice to meet you.] 然后愉快的py。
二次握手: A---->B: [I'm A.]
B---->A: [Hello A, I'm B.]
如果A收到了“Hello A,I'm B”,愉快的py; 如果A没有收到“Hello A,I'm B”,那么while(true){ A---->B: [I'm A.] }, 疯狂握手。
三次握手的目的是确认A--->B, B--->A这两个信道都是可靠的;如果只有两次握手就无法确认B--->A的信道是否可靠。如果只需要A--->B信道可靠,那就类似于UDP的需求了。
四次挥手
概览
连接的任何一方都可以发起关闭连接,在传统情况下往往由客户端来发起关闭连接,如下图所示。

- 第一步:客户端发送FIN包(包含了客户端的序列号M),此外FIN包还包含了一个ACK段用于确认对方最后一次发送的数据。
- 第二步:服务器收到客户端发送的FIN包后,将M值+1作为响应的ACK值,表明它已经成功接收到来自客户端发送的FIN。此时,处于上层的应用程序会被告知连接的另一方发起了关闭连接的请求,这将导致应用程序发动自己的关闭操作。服务器从被动关闭者变为主动关闭者,向客户端发送FIN(包含了服务器的序列号N)。
- 第三步:为了完成连接的关闭,客户端发往服务器最后的报文段中包含了一个确认服务器发送的FIN的ACK字段。
为什么是四次挥手?
四次挥手: A ---> B, [A: ‘我想关闭连接’]
B ---> A, [B: ‘好的,我知道了,我不要收到你的东西了’]
B ---> A, [B: ‘我想关闭连接’]
A ---> B, [A: ‘好的,我知道了,我也不要收到你的东西了’]
主动方发送关闭请求,被动方接受并确认请求后,被动方就无法收到主动方发送的数据了。在前两次挥手后,服务器就无法收到客户端发送的数据了(服务器释放了关于客户端的资源),但是服务器可以给客户端发送数据,所以有了第三次、第四次挥手。