
TCP的三次握手
和四次挥手
实质就是TCP通信的连接
和断开
。

1.三次握手
TCP协议位于传输层
,作用是提供可靠的字节流服务,为了准确无误地将数据送达目的地,TCP协议采纳三次握手策略。
==三次握手原理:==
第1次握手:客户端发送一个带有
SYN(synchronize)
标志的数据包给服务端;第2次握手:服务端接收成功后,回传一个带有
SYN/ACK
标志的数据包传递确认信息,表示收到了;第3次握手:客户端再回传一个带有ACK标志的数据包,握手结束。
其中:SYN标志位数置1,表示建立TCP连接;ACK标志表示验证字段。
ACK:
此标志表示应答域有效
。TCP应答号将会包含在TCP数据包中。 有两个取值:0和1,1表示应答域有效,反之为0。
SYN(SYNchronization) :
在连接建立时用来同步序号
。SYN置1就表示这是一个连接请求或连接接受报文
。 当SYN=1而ACK=0时,表明这是一个连接请求报文;
SYN=1和ACK=1,对方同意建立连接。
可通过以下趣味图解理解三次握手:

三次握手详细说明:
- 第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
- 第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,,完成TCP三次握手。 完成了三次握手,客户端和服务器端就可以开始传送数据。
2.四次挥手
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
==四次挥手原理:==
第1次挥手:客户端发送一个FIN,用来关闭客户端到服务端的数据传送,客户端进入FIN_WAIT_1状态;
第2次挥手:服务端收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1
(与SYN相同,一个FIN占用一个序号),服务端进入CLOSE_WAIT状态;
客户端进入FIN_WAIT_2状态
第3次挥手:服务端发送一个FIN,用来关闭服务端到客户端的数据传送,服务端进入LAST_ACK状态;
第4次挥手:客户端收到FIN后,客户端t进入TIME_WAIT状态,接着发送一个ACK给Server,
确认序号为收到序号+1,服务端进入CLOSED状态,完成四次挥手。
其中:FIN(finis)
标志位数置1,表示断开TCP连接。
可通过以下趣味图解理解四次挥手:

LISTEN:等待从任何远端TCP 和端口的连接请求。
SYN_SENT:发送完一个连接请求后等待一个匹配的连接请求。
SYN_RECEIVED:发送连接请求并且接收到匹配的连接请求以后等待连接请求确认。
ESTABLISHED:表示一个打开的连接,接收到的数据可以被投递给用户。连接的数据传输阶段的正常状态。
FIN_WAIT_1:等待远端TCP 的连接终止请求,或者等待之前发送的连接终止请求的确认。
FIN_WAIT_2:等待远端TCP 的连接终止请求。
CLOSE_WAIT:等待本地用户的连接终止请求。
CLOSING:等待远端TCP 的连接终止请求确认。
LAST_ACK:等待先前发送给远端TCP 的连接终止请求的确认(包括它字节的连接终止请求的确认)
TIME_WAIT:等待足够的时间过去以确保远端TCP 接收到它的连接终止请求的确认。
TIME_WAIT 两个存在的理由:
1.可靠的实现tcp全双工连接的终止;
2.允许老的重复分节在网络中消逝。CLOSED:不在连接状态(这是为方便描述假想的状态,实际不存在)
3.为什么需要三次握手,两次不行吗?
弄清这个问题,我们需要先弄明白三次握手的目的是什么,能不能只用两次握手来达到同样的目的。
- 第一次握手:客户端发送网络包,服务端收到了。 这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
- 第二次握手:服务端发包,客户端收到了。 这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时==服务器并不能确认客户端的接收能力是否正常==。
- 第三次握手:客户端发包,服务端收到了。 这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。
另一个种解释:
因为某些原因,S没有收到C的包,过了一段时间后才收到,S认为这是两个请求,而C认为是一个请求,从而在2次握手后进入等待状态,造成状态不一致。
如果在3次握手的状态下,S收不到最后的ACK包,自然不会认为连接建立成功。
所以3次握手,就是为了解决网络信道不可靠的问题。
因此,需要三次握手才能确认双方的接收与发送能力是否正常。

4.三次握手过程中可以携带数据吗?
其实第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据
为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据。因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。
也就是说,第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易受到攻击了。而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。
5.挥手为什么需要四次?
因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,”你发的FIN报文我收到了”。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次挥手。
6.为什么客户端需要等待超时时间
这是为了保证对方已经收到ACK。
- 因为假设客户端发送完最后一份ACK后,就释放了链接,一旦ack包在网络中丢失,服务端将一直停留在最后的确认状态。
- 如果客户端发行完最后一份ACK后,等待一段时间,这时服务端又没有收到ACK,会重发FIN包,客户端会响应这个FIN包,重发ACK包,并刷新超时时间,也是为了保证在不可靠的网络链路中进行可靠的链接断开确认
- Post title: TCP三次握手四次挥手
- Create time: 2019-03-16 14:45:00
- Post link: 2019/03/16/三次握手四次挥手/
- Copyright notice: All articles in this blog are licensed under BY-NC-SA unless stating additionally.