重要字段及含义:
- Seq:序号
- Ack:确认号
- ACK:确认序号有效
- SYN:请求连接
- FIN:请求释放连接
三次握手
握手之前客户端结束CLOSED状态,服务器端也结束CLOSED阶段,并进入LISTEN状态。
第一次握手: 客户端向服务端发送tcp报文
- SYN标记,表示“请求建立连接”
- 序号为Seq=X
客户端进入请求已发送状态(SYN-SENT)
第二次握手: 服务器端收到客户端tcp报文,并返回一段tcp报文
- SYN和ACK标记,表示“告诉客户端,服务器收到了你的数据并同意创建新连接”
- 序号为Seq=y
- 确认号为Ack=x+1,将收到客户端的序号Seq加1作为自己确认号Ack的值
结束LISTEN状态,服务器端进入请求已收到状态(SYN-RCVD)
第三次握手: 客户端收到服务器端确认收到的tcp报文之后,确认了与服务器端的数据传输是正常的,结束请求已发送状态(SYN-SENT),发送最后一段tcp报文
- ACK标记,表示“确认收到服务器端同意连接的信号”
- 序号为Seq=x+1,将收到的服务器端的确认号Ack作为自己的序号
- 确认号为Ack=y+1,将收到服务器端的序号Seq加1作为自己确认号Ack的值
客户端进入确认连接状态(ESTABLISHED),服务器端收到客户端的“确认收到”的tcp报文之后,服务器端结束请求收到状态(SYN-RCVD),进入确认连接状态(ESTABLISHED)
为什么需要三次握手,两次不行
- 无法阻止历史连接:没有中间状态来阻止历史连接,导致可能建立一个历史连接,造成资源浪费。
- 无法可靠的同步双方序列号:两次握手只保证了一方的序列号能被对方成功接收,没办法保证双方的序列号都能被确认接收。
- 会造成双方资源的浪费:如果客户端的 SYN 阻塞了,重复发送多次 SYN 报文,那么服务器端就会对每个请求都建立一个连接,造成不必要的资源浪费。
是什么半连接状态
服务器第一次收到客户端的 SYN 之后,就会处于请求收到状态( SYN_RCVD),此时双方还没有完全建立连接,服务器会把此种状态下的请求连接放在一个队列里,我们把这种队列称之为半连接队列。
当然还有一个全连接队列,就是已经完成三次握手,完全建立连接的就会放在全连接队列中。如果队列满了就有可能会出现丢包现象。
重传次数问题
服务器发送完tcp报文,如果未收到客户确认包,服务器进行第一次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。
握手过程中可以携带数据吗
第一次和第二次握手不可以携带数据,第三次可以携带数据。如果第一次握手可以携带数据,有人恶意对服务器进行攻击,每次都在SYN报文中传入大量数据,这会让服务器花费很多时间、内存空间来接收这些报文。会让服务器更加容易受到攻击。
而第三次握手,此时客户端已经处于确认连接状态(ESTABLISHED ),所以能在报文中携带数据。
四次挥手
四次挥手指TCP连接的释放,释放必须是一方主动释放,另一方被动释放。刚开始双方都处于确认连接状态(ESTABLISHED ),假如是客户端先发起关闭请求。
第一次挥手:客户端向服务器发送一段tcp报文,结束确认连接状态(ESTABLISHED )。
- FIN标记,表示“请求释放连接“
- 序号为Seq=u
客户端进入终止等待1状态(FIN-WAIT-1),客户端停止向服务端发送数据,但是仍然能接收到服务端的数据
第二次挥手:服务器接收到客户端的tcp报文请求释放连接,服务器结束确认连接状态(ESTABLISHED ),返回客户端tcp报文。
- ACK标记,表示“接收到客户端的释放连接请求”
- 序号为Seq=v
- 确认号为Ack=u+1,将收到客户端的序号Seq加1作为自己确认号Ack的值
服务器进入关闭等待状态(CLOSE-WAIT),客户端收到服务器的tcp报文后,客户端结束终止等待1状态(FIN-WAIT-1),进入终止等待2状态(FIN-WAIT-2)
第三次挥手:如果服务器准备好了释放连接,再次向客户端发送tcp报文
- FIN和ACK标记,表示“已经准备好释放连接”
- 序号为Seq=w
- 确认号为Ack=u+1,将收到客户端的序号Seq加1作为自己确认号Ack的值
服务器结束关闭等待状态(CLOSE-WAIT),进入最后确认状态(LAST-ACK)。服务器停止向客户端发送数据。
第四次挥手:客户端接收到服务器的tcp报文,返回一段tcp报文
- ACK标记,表示“接收到服务器准备释放信号”
- 序号为Seq=u+1,将收到服务器的确认号Ack作为自己序号Seq的值
- 确认号为Ack=w+1,将收到服务器的序号Seq加1作为自己确认号Ack的值
客户端结束终止等待2状态(FIN-WAIT-2),进入时间等待状态(TIME-WAIT)。
服务器接收到客户端的tcp报文后,结束最后确认状态(LAST-ACK),进入CLOSED状态。正式关闭服务器到客户端的连接。
客户端等待2MSL1后,结束时间等待状态(TIME-WAIT),进入CLOSED状态。
为什么是四次挥手
建立连接:第二次握手的时候,服务器发送给客户端的报文表示(SYN)同意建立连接和(ACK)确认收到报文,是在一次握手中就完成了。
释放连接:服务器发送报文(FIN)同意释放连接和(ACK)确认收到报文是在第二次和第三次挥手中完成的。当收到客户端的释放连接请求之所以不能立即释放连接,是因为可能数据还未处理完成。所以先返回(ACK)确认收到报文,结束(CLOSE-WAIT)关闭等待状态之后,再发送(FIN)释放连接报文。
2MSL时间等待状态
服务器端在1MSL内没有收到客户端的ACK确认报文,就会再次向客户端发出FIN报文。当客户端2MSL内没有再收到服务器的FIN报文,才能进入CLOSED状态。保证客户端发送的ACK报文能到达服务端
网络中最大的存活时间,一个发送和一个回复所需的最大时间 ↩︎