TCP协议(三)
TCP协议(三)
- 一、介绍TCP三次握手
- 关于第三次握手
- 二、TCP三次握手的意义
- 三、介绍TCP四次挥手
- 关于四次挥手
- 四、tcp为什么要建立连接
- 五、主动断开连接的一方为什么要维持TIME_WAIT状态一段时间
- 六、如何让挂掉的服务器立刻重启,不用等待2MSL的时间
一、介绍TCP三次握手
第一次握手。由客户端向服务端发送请求连接的报文,客户端的连接状态变为SYN_SENT,当服务端收到请求报文,服务端连接进入SYN_RCVD状态(半连接状态),这就是这一次握手。
第二次握手。服务端向客户端发送确认请求报文,报文类型为SYN和ACK,既是对客户端请求连接报文的确认,也是向客户端发送连接请求报文,所以报文类型为SYN+ACK,当客户端收到服务端发来的确认请求报文,客户端的连接状态就变为ESTABLISHED,客户端就认为自己和服务端建立了连接,这就是第二次握手。
第三次握手。客户端也要对服务端发来的确认请求报文做出确认响应,所以向服务端发送确认请求报文的确认报文,服务端收到确认报文,服务端的连接状态就变为ESTABLISHED,服务端也就认为自己和客户端建立了连接,这就是第三次握手。
关于第三次握手
当第三次握手中服务端一段特定时间没有收到确认报文,服务端会认为自己发送的确认请求报文丢失了,服务端会通过超时重传机制,向客户端再次发送SYN和ACK类型的确认请求报文,当连续发送几次后,依然没有收到确认报文,服务端会向客户端发送RST类型的报文,告诉客户端连接状态不一致,要求客户端重新建立连接,即重新进行三次握手,服务端会将连接重SYN_RCVD状态变为CLOSE状态,将连接关闭。
当第三次握手中服务端没有收到客户端的确认报文时,第三次握手没有成功,客户已经建立了连接,客户端向服务端发送数据报文,服务端收到数据报文,会将数据报文丢掉,将连接重SYN_RCVD状态变为CLOSE状态,对客服端发送RST类型的报文,要求客户端重新进行三次握手建立连接。
二、TCP三次握手的意义
三次握手可以最小成本检验客户端能否与服务端进行全双工通信。第二次握手中,客户端收到服务端对连接请求的确认报文,就能确认服务端可以收到客服端发送的消息。第三次握手中,服务端收到客户端发来的确认报文就能知道客户端能收到服务端发送的消息。这样就能检验客户端能否与服务端进行全双工通信了。
防止单主机对服务端进行SYN洪水攻击(DoS攻击)。如果是一次握手和两次握手就能让服务端建立连接,客户端可以对服务端发送大量的SYN类型的报文去请求连接,服务端收到连接请求报文,会建立连接,连接多了,需要对连接进行管理,连接本质就是文件描述符,一个服务器的文件描述符有限,发送大量SYN报文建立连接就能消耗服务端的资源。如果是三次握手客户端必须先建立连接才能让服务端建立连接,所以在单主机的情况下,如果想要消耗服务端的资源,客户端必须先消耗资源,一般服务端的资源比客服端多,单主机的情况下,单主机会先资源消耗完。这样就能防止单主机对服务端进行SYN洪水攻击。这种主机就叫做肉鸡,这种攻击也叫做DoS攻击(拒绝服务攻击)。
三、介绍TCP四次挥手
TCP三次握手一定是客户端先向服务端发送连接请求。但是TCP四次挥手可以是服务端先发送关闭连接,也可以是客户端先向服务端发送关闭连接。以客服端先向服务端发送关闭连接为例。
第一次挥手。客户端向服务器发送FIN类型的关闭连接报文,客服端的连接状态变为FIN_WAIT_1,服务端收到客户端的关闭连接报文,服务端的连接状态变为CLOSE_WAIT。
第二次挥手。服务端向客户端发送连接关闭的确认报文,客户端收到服务端的确认报文,客户端的连接状态就变为FIN_WAIT_2。此时,服务端向客户端发送数据报文,会被客户端丢弃,因为客服端的应用层不会再接受数据,但是服务端发送FIN类型的关闭连接报文,客户端传输层会接受,并会对报文进行确认。
第三次挥手。服务端向客户端发送FIN类型的关闭连接报文,服务端的连接状态变为LAST_ACK,客户端收到关闭连接的报文,客户端连接状态变为TIME_WAIT。
第四次挥手。客户端向服务端发送连接关闭的确认报文,服务端收到确认报文连接状态变为CLOSE。
关于四次挥手
主动发起关闭连接的一方最终会先进入TIME_WAIT状态,等待2MSL的时间连接会变为CLOSED状态。被动断开连接的一方,经过两次挥手进入CLOSE_WAIT状态,经过四次挥手连接变为CLOSED状态。
若服务器出现大量连接的状态为CLOSE_WAIT,可能有两个原因:第一个可能是服务器应用层中忘记close套接字文件描述符,客户端关闭了连接,服务端没有关闭连接的操作。第二个原因可能是服务器压力过大,处理过多的数据报文,还没来得及关闭连接。
四、tcp为什么要建立连接
因为建立连接是保证可靠性的前提基础。通过三次握手的机制建立连接,在客户端和服务端的传输层才会存在连接的结构体。这是因为连接结构的存在,才能进行超时重传,流量控制,拥塞控制等策略保证通信的可靠性。
五、主动断开连接的一方为什么要维持TIME_WAIT状态一段时间
1.为了保证最后一个确认报文尽可能被对方收到。需要维持二倍的MSL(报文最长存活时间),如果最后挥手的确认报文丢失,被动断开的一方没有收到确认报文,被动断开的一方会认为自己的FIN丢失没有到达对方,会启动超时重传机制,发送FIN报文给对方,维持的2MSL这段时间内,被动断开一方的FIN报文可到达主动断开连接的一方,主动断开连接的一方再次收到FIN报文,就知道确认断开连接报文对方没有收到,就会再次发送确认报文,以保证对方收到确认报文,断开连接。
2.让网络中滞留的数据报文在2*MSL的时间内到达目的机,被目的机丢掉,防止报文过段时间到达新建立的连接中,导致数据混淆。
六、如何让挂掉的服务器立刻重启,不用等待2MSL的时间
服务器可能由于压力过大(连接过多),导致服务器挂掉(主动断开连接),可能服务器只用于抢购等业务,为了减少损失,如何让服务器中的连接不用处于TIME_WAIT状态2MSL的时间,处于TIME_WAIT状态的连接对应的端口号是不能使用的,只有等过了2MSL的时间,端口才能使用,用户都是通过URL来访问服务资源,URL有端口号来表示不同的服务,怎样才能让端口立刻使用,不用等2MSL的时间。
使用地址复用,保证连接套接字文件描述符绑定的ip和端口处于TIME_WAIT状态依旧可以使用,立即让服务器重新启动。
int opt=1;
setsockopt(_listenSockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));