TCP三次握手是为了确保两端套接字可以正常通信即两端的收发能力都是正常的,在正式传输数据前进行试探的一种方式,就好比两个人对话,因为不能确定对方是否领会了你的意思,需要频频询问"听懂了吗?",对方频频应答"嗯嗯"。
一、TCP建立连接的过程
0.准备
服务端套接字从主动套接字(CLOSED)变为被动打开(LISTEN)。
服务端通过调用socket,bind和listen来达到一个准备好接受外来连接的状态。
三个函数参照博客
1.第一次握手
客户端通过connect发起主动打开(active open)。
客户TCP端发送一个序号(SYN),SYN告诉服务端将在即将建立的连接中发送的数据的初始序列号。
具体过程是将自己的SYN标志位置为1,在发送一个seq(初始序号,为了防止受到攻击是随机产生的)。
关于SYN和ACK的具体结构参照TCP报文格式
2.第二次握手
服务端收到客户端的SYN后,回复ACK(即确认序号—客户端的SYN+1)和自己的序号(SYN)。具体过程是服务端将自己的SYN和ACK标志位同时置为1,并把客户端发送的初始序号+1放在自己的确认序号位置,再把自己随机生成的seq放在序号的位置。
3.第三次握手
客户端回复一个ACK(即确认序号—服务端发送的SYN+1),并且这次可以在DATA字段携带数据了。具体过程为把ACK标志位置为1,再把服务端发送的初始序号+1放在确认序号的位置。
二、注意事项
1.为什么不能用两次握手建立连接?
防止已经失效的连接请求报文在传送到服务端,再次建立连接,导致不必要的问题和资源的浪费。
思考这样一个场景,假如只有两次握手,客户端发送了一个SYN报文,发起连接请求,但是由于在网络节点中滞留的时间太长,服务端还没收到也就没有发送ACK确认,但是客户端认为服务端没有收到重传后通过两次握手二者建立正常连接,随后结束通信后正常断开连接。之后滞留的SYN报文达到服务端,服务端发送ACK确认连接建立,但是客户端迟迟没有数据发送,白白浪费了资源。
如果是三次握手的话,滞留的报文到达后,客户端回复ACK但是客户端没有第三次握手相应,从而知道客户端没有连接请求。
2.TCP数据传输过程。
传输数据的过程与三次握手类似,无论是服务端还是客户端发送数据都需要对端回复一个ACK来确认。
3.SYN FLOOD是什么?
SYN洪水攻击,就是攻击者发送大量的SYN报文给服务端请求连接,攻击者发送完毕后不需要回复ACK,而服务端需要等待一段时间后才会丢掉这个未完成的连接,服务器为了维护这个大量的半连接队列浪费大量的资源。
4.为什么第三次握手可以携带数据?
第一次握手:服务端确认了客户端的发送能力正常。
第二次握手:客户端确认了服务端的发送和接受能力正常。
第三次握手:服务端确认了客户端的发送能力正常。
综上,第三次握手前客户端已经处于ESTABLISHED状态,就是说客户端已经建立连接了,所以客户端向服务端发送数据即第三次握手携带数据。
如果第一次握手就携带数据,服务端会更容易收到攻击,攻击者携带大量数据会给服务端增大压力去处理这些数据。