过程如下图

三次握手
在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接,客户端和服务器端是相对的概念,本文我们以客户端向服务器端发送为例。
第一次握手:客户端向服务器端发送一个SYN报文,报文中包含了一个动态生成的序列号i(至于为什么动态生成可以自己想想),这时,客户端处于SYN_SEND状态(打开一个连接),表示已向服务器发送了连接请求;
第二次握手:服务器端接收到连接请求,认为可以建起连接,回发一个ACK确认报文,内容将序列号i+1,同时,生成一个序列号j,发送一个SYN报文,内容为序列号j,服务器端处于SYN_REVD状态(连接请求已到达,等待确认),表示等待客户端确认连接;
第三次握手:客户端接收到服务器端的反馈,立马发送一个ACK报文,内容为j+1,便是确认连接,这时客户端状态为establish(正常传输状态)
服务器端接收到ACK报文后,连接建立完成。
四次挥手
依然以客户端主动发起断开连接为例。
第一次挥手:客户端主动发起断开请求,动态生成一个序列号M,向服务器发送一个FIN报文,此时,客户端处于FIN_WAIT1状态;
第二次挥手: 服务器端收到客户端的断开请求,发送确认报文ACK(M+1),告诉客户端,我知道了,等我处理完这波数据,此时服务器状态为CLOSE_WAIT;
第三次挥手: 等服务器处理完,准备要断开连接了,向客户端发送一个FIN报文,伴有动态生成的序列号N,此时服务器状态LAST_ACK;
第四次挥手: 客户端收到服务器发来的断开连接报文,则回复一个ACK报文N+1,表示我确认断开连接,这时客户端处于 TIME_WAIT状态 ,很关键的状态,面试高频出现;
服务端收到 ACK 报文之后,就处于关闭连接了,处于 CLOSED 状态。
扩展
TIME_WAIT状态
为什么客户端发送 ACK 之后不直接关闭,而是要等一阵子才关闭。这其中的原因就是, 要确保服务器是否已经收到了我们的 ACK 报文, 如果没有收到的话,服务器会重新发 FIN 报文给客户端,客户端再次收到 ACK 报文之后,就知道之前的 ACK 报文丢失了,然后再次发送 ACK 报文。 至于 TIME_WAIT 持续的时间至少是一个报文的来回时间。一般会设置一个计时,如果过了这个计时没有再次收到 FIN 报文,则代表对方成功收到 ACK 报文,此时处于 CLOSED 状态。
半连接
即发送了SYN包还未收到ACK确认包的连接状态为半连接状态,还未完成三次握手TCP连接。半连接队列:在三次握手协议中,服务器维护一个半连接队列; 该队列为每个客户端的SYN包(SYN=i)开设一个条目, 该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。 这些条目所标识的连接在服务器处于SYN_ RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。
DOS攻击
因为服务器会维护一个半连接的队列,那如果我们向服务器发送大量伪造的无效的半连接请求,便会消耗cpu和内存, 当伪造的SYN包长时间占用半连接队列,正常的SYN请求遍会被抛弃,服务器便面临着网络阻塞甚至系统瘫痪的风险, 这也是比较常见的一种DOS攻击方式。