一开始的时候,客户端和服务器都处于CLOSED的状态,然后服务器开始监听某个端口,进入LISTEN状态:
三次握手,首先由客户端向服务端发起连接请求,此为第一次握手;
然后服务端接收到来自客户端的请求之后,向客户端回复已经收到连接请求了,可以开始连接了,并转为等待连接模式,此为第二次握手;
当客户端收到来自服务端的确认码之后,在次向客户端发送确认消息,并开始连接,此为第三次握手;
第一次握手(由客户端发出SYN = 1,seq = x),发送完毕后客户端处于SYN_SEND状态
第二次握手(有服务器发出SYN = 1,ACK = 1,seq = y,ACKnum = x+1)发送完毕后,发送完毕后服务器端进入SYN_RCVD状态
第三次握手(由客户端发出ACK = 1,ACKnum = y+1)发送完毕后客户端进入ESTABLISHED的状态,当服务器端接收到这个包时,也进入ESTABLISHED状态,TCP握手完成,可以开始进行数据传输。
三次握手是为了确保连接的成功,客户端和服务端都确认可以被连接然后第三次握手建立连接,如果是两次,那么建立的连接就不是百分百准确的,有可能连接失败;四次的话就有点多余了,既然三次握手已经能够准确的建立连接了,没必要再来一次,浪费时间和空间。
初始状态为客户端和服务端处于连接状态,并且数据已经发送完毕,没有要继续发送的数据了,然后客户端要开始断开连接:
客户端首先要向服务端发送消息,告诉服务器端,我没有要传输的数据了,可以进行断开了,此为第一次挥手;当服务器端收到来自客户端的消息之后,回复客户端他已经知道了,准备好了挥手,此为第二次回收;当发送完消息一段时间之后,服务器端发送消息告诉客户端我已经准备好了,可以进行断开了,此为第三次挥手;当客户端收到消息之后,客户端断开与服务端的连接,此为第四次挥手,至此,客户端和服务端的连接彻底断开;
1. 第一次挥手(FIN=1,seq=u),发送完毕后,客户端进入FIN_WAIT_1 状态
2. 第二次挥手(ACK=1,ack=u+1,seq =v),发送完毕后,服务器端进入CLOSE_WAIT 状态,客户端接收到这个确认包之后,进入 FIN_WAIT_2 状态
3. 第三次挥手(FIN=1,ACK1,seq=w,ack=u+1),发送完毕后,服务器端进入LAST_ACK 状态,等待来自客户端的最后一个ACK。
4. 第四次挥手(ACK=1,seq=u+1,ack=w+1),客户端接收到来自服务器端的关闭请求,发送一个确认包,并进入 TIME_WAIT状态,等待了某个固定时间(两个最大段生命周期,2MSL,2 Maximum Segment Lifetime)之后,没有收到服务器端的 ACK ,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入 CLOSED 状态。服务器端接收到这个确认包之后,关闭连接,进入 CLOSED 状态。
TCP的四次挥手过程就像两个人在打电话,当A对B说我没什么要说的了,B回复说我知道了;此时B可能还有话对A说,当B说完之后,B告诉A我说完了,你可以挂了,然后再有A来挂断电话。因为TCP通信是双端通信,客户端和服务端都可以向对方发送消息,所以要确定两边都没有数据可发送了之后才能彻底断开连接,因此需要四次挥手;
2msl 两个报文的生命周期
TCP进入三次握手前,服务端会从CLOSED状态变成LISTEN状态,同时在内部创建两个队列:半连接队列(SYN队列和全连接队列(ACCEPT队列)。
TCP三次握手是,客户端发送SYN到服务端,服务端收到后,便回复SYN和ACK,状态由LISTEN变为SYN_RCVD,此时这个连接就被推入了SYN队列,及半连接队列。
当客户端回复SCK,服务端接收后,三次握手就完成了。这是链接会等待被具体的应用取走,再被取走之前,它被推入ACCEPT队列,即为全连接队列。
SYNFlood是一种典型的DOS(Denial of Service拒绝服务)攻击,她在短时间内,伪造不存在的IP地址,向服务器大量发起SYN报文,当服务器回复SYN+ACK报文后,不会受到ACK会议康报文,导致服务器上建立了当量的半连接,半连接队列被挤占满了就无法处理正产的TCP请求了。
TCP是面向流,没有界限的一串数据。TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包的划分,所以在业务上认为,一个完整的包可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包进行发送,这就是所谓的TCP粘包和拆包问题。