TCP把连接作为最基本的对象,每一条TCP连接都有两个端点,这种端点叫作套接字(socket),由IP地址 + 端口号组成。例如,若IP地址为192.3.4.16 而端口号为80,那么得到的套接字为192.3.4.16:80。

一、三次握手建立连接

1、什么是三次握手?
三次握手,就是客户端与服务器建立连接之前,先进行三次简单的通信,成功之后才正式建立连接。其目的是为了确认信道是否安全,双方是否具有收发消息的能力。

客户端:老铁,能听到我说话吗?

服务器:能听到。你能听到我说话吗?

客户端:也能听到。好了,那我开始说正事了。

如图所示

TCP三次握手建立连接和四次挥手释放连接_四次挥手


2、铺垫知识

序号(sequence number):seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。

确认号(acknowledgement number):ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack=seq+1。

标志位(Flags):共6个,即URG、ACK、PSH、RST、SYN、FIN等。具体含义如下:

URG:紧急指针(urgent pointer)有效。
ACK:确认序号有效。(为了与确认号ack区分开,我们用大写表示)
PSH:接收方应该尽快将这个报文交给应用层。
RST:重置连接。
SYN:发起一个新连接。
FIN:释放一个连接。

seq序号、ack序号:用于确认数据是否准确,是否正常通信;
标志位:用于确认/更改连接状态。

3、三次握手的详细过程

最开始的时候客户端和服务器都是处于CLOSED状态。主动打开连接的为客户端,被动打开连接的是服务器。

1)TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器进入LISTEN(监听)状态;

2)TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文。
报文首部中的同步位SYN=1,同时选择一个初始序列号 seq=x ;此时TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。

3)TCP服务器收到请求报文后,如果同意连接,则发出确认报文。
确认报文中ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y;此时TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。

4)TCP客户进程收到确认后,还要向服务器给出确认。
确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1;此时TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。

5)当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

TCP三次握手建立连接和四次挥手释放连接_客户端_02

TCP三次握手建立连接和四次挥手释放连接_tcp/ip_03


SYN:用于建立连接。

ACK:用于确定收到了请求。

seq:发送自己的数据。

ack:发送接收到的对方的数据。

3、为什么是三次握手,而不是2次、4次?
确认对方具有收发能力需要一来(询问)、一回(应答),共2次通信;那么客户端和服务器各自向对方确认,应该是4次握手。但为了节省,服务器端将应答和询问合在一次通信中完成,所以变成了3次。

客户端:老铁,能听到我说话吗?(询问)

服务器:能听到。你能听到我说话吗?(应答、询问)

客户端:也能听到。好了,那我开始说正事了。(应答)

也有一些比较复杂的解释:

一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。

如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

4、三次握手过程中,如果丢包咋办?
不同步骤丢包,处理有些差别。基本都是丢包的话,会重传、重试,超过阈值后放弃。

因为有重试重传的机制,容易被别有用心地进行攻击。如SYN攻击:

攻击客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。

SYN 攻击是一种典型的 DoS/DDoS 攻击。

三、四次挥手释放连接

1、详细过程

TCP三次握手建立连接和四次挥手释放连接_客户端_04


数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。

2、为什么建立连接是三次握手,关闭连接确是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里,合并发送给客户端。

而关闭连接时,服务器收到对方的FIN报文,仅仅表明对方不再发送数据了,但是还能接收数据;而自己也未必全部数据发送完毕,所以服务器可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文表示同意现在关闭连接。因此,在关闭连接时,ACK和FIN一般都会分开发送,从而导致多了一次。