关于三次握手图解
如图,三次握手中Client发送端,Server为接收端
建立连接前需要Server端先监听端口,因此Server建立连接前的初始状态就是LISTEN状态,
-
Client端准备建立连接,先发送一个SYN同步包,发送完同步包后Client端的状态就变成了SYN_SENT,
-
Server收到SYN后同意建立连接会向Client端回复一个ACK,由于TCP是双工传输,Server端也会同时像Client端发送一个同步请求SYN申请Server向Client方向建立连接,发送完ACK和SYN后Server端的连接状态就变成了SYN_RCVD,
-
Client收到Server的ACK后,Client端的连接状态就变成了ESTABLISHED,同时Client端向Server端发送ACK响应,回复Server端的SYN请求,Server端收到Client端的ACK后,Server端的连接状态就变成ESTABLISHED状态,
此时建联完成。
三次握手是为了建立双向的连接。
建联中可能出现SYN洪水攻击,其产生的原因以及解决方案。
SYN洪水攻击发生的原因:就是Server端收到Client端的SYN请求后,发送了ACK和SYN,但是Client端不进行回复,导致Server端大量的连接出现在SYN_RCVD状态,进而影响其他请求的建联,
解决方案:可以通过设置TCP的参数(修改重试次数)SYN_retries=0加快半连接的回收速度,或者(修改等待数)syn_backlog=2048调大MAC来应对少量的SYN洪水攻击。
关于四次挥手图解
如图,四次挥手中Client发送端,Server为接收端
断连四次挥手,通信双方都可以发起,这里举例Client先发起
- Client向Server发起了一个FIN包表示Client端已经没有数据要发送,然后Client端就进入FIN_WAIT_1状态,
- Server端收到FIN后返回ACK然后进入CLOSE_WAIT状态,此时Server属于半关闭状态,因为此时Client向Server方向已经不会再发送数据了,可是Server向Client端可能还有数据要发送,
- 当Server端数据发送完毕后Server端向Client端发送FIN表示Server端也没有数据要发送,这是Server进入LAST_ACK状态,就等待Client端的应答就关闭连接了,
- Client端收到Server端的FIN后回复ACK然后进入TIME_WAIT状态,TIME_WAIT状态下需要等待2MSL就是最大报文段生存时间(一个IP数据包能在互联网上生存的最长时间)来保证连接的可靠关闭,之后才会进入CLOSED状态,而Server端收到ACK后直接进入CLOSED状态。
为什么要等待两倍的MSL才关闭连接?
原因:
1.要保证TCP协议的全双工连接能够可靠关闭
2.保证这次连接中重复的数据段能够从网络中消失,防止端口被重用的时候可能会产生数据混淆。
在断联的时候可能会出现大量的socket出现在TIME_WAIT或者CLOSE_WAIT状态的问题
解决方案:一般开启TCP参数在 /etc/sysctl.conf中加入
net.ipv4.tcp_tw_recycle = 1 (表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭)加快TIME_WAIT状态的回收。
而出现大量CLOSE_WAIT状态一般是被动关闭的一方可能出现代码的bug,没有正确关闭连接导致的
总结:
从这个交互流程中可以看出不论是建联还是断联,都是需要在两个方向上进行,只不过建联时Server端的SYN和ACK合并为一次发送,而断开连接是两个数据停止时间可能是不同的,所以无法合并FIN和ACK发送,这就是建联的时候必须要三次握手而断联的时候必须要四次挥手的原因。