TCP协议三次握手四次挥手
该文档涵盖了参考模型传输层的TCP协议知识点。
阅读完该文档后,您将会了解到:
- TCP协议中的三次握手
- TCP协议中的四次挥手
- TCP协议的常见面试问题
错误之处还望指正。
重点面试内容: 发送的内容和状态(syn/ack/fin/seq) 头条面试遇到过
位码即tcp标志位,有6种标示:
- SYN(synchronous 开始同步)
- ACK(acknowledgement 确认)
- FIN(finish结束)
- Sequence number(序列号)
- Acknowledge number(确认号)
- PSH(push传送)
- RST(reset重置)
- URG(urgent紧急)
TCP协议中的三次握手
如图:
主要有两个标志位: SYN是否请求连接/同步 和 ACK确认收到请求
序列号的用途是标识特定某一次连接;
- 第一次握手:客户端发送 SYN(是否请求连接;1是) 和 seq(序列号,标识特定的本次连接J) 到服务器,客户端进入SYN_SEND状态,等待服务器确认;
- 第二次握手:服务器收到连接请求,确认ACK标志位是1,即客户端发起了请求; 服务器发送__ACK(是否收到请求;1是) 和 ack(J+1,特定某次请求); 同步客户端SYN(是否请求连接;1是)和seq(序列号,标识特定的本次连接K)__,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的连接请求,向服务器发送__ACK(是否收到请求;1是) 和 ack(K+1,特定某次请求)__,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
次数 | 客户端状态 | 服务器状态 | 发送数据 |
---|---|---|---|
第一次握手 | SYN_SEND | SYN:标志位1; seq:序列号,随机数J | |
第二次握手 | established | SYN_REVC | 标志位SYN和ACK: 1; ack:确认号,J+1; seq:序列号,随机数K |
第三次握手 | established | established | 标志位ACK: 1; ack:确认号,K+1 |
我的理解:
1、状态变换:
syn(同步), syn_send / syn_recv 英语单词很容易理解;
- 为什么要三次握手
书: 为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误
说白了就是:防止了服务器端的一直等待而浪费资源
SYN攻击
面试一句话: 在半连接状态下,客户端发送大量不存在ip给服务器,造成正常的SYN丢弃。
在三次握手过程中,服务器发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect).
此时服务器处于Syn_RECV状态.当收到ACK后,服务器转入ESTABLISHED状态.
Syn攻击就是 客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,
由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
Syn攻击是一个典型的DDOS攻击。
检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击.在Linux下可以如下命令检测是否被Syn攻击
netstat -nap grep SYN_RECV
netstat -n -p TCP grep SYN_RECV
一般较新的TCP/IP协议栈都对这一过程进行修正来防范Syn攻击,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等. 但是不能完全防范syn攻击。
TCP协议中的四次挥手
注意:中断连接端可以是Client端,也可以是Server端,那么就是图上的流程反过来操作
解释(以客户端发起断开为例子)
如图:
主要有两个标志位: FIN是否已完成数据传送 和 ACK确认收到请求
序列号的用途是标识特定某一次连接;
- 第一次握手:客户端发送 FIN(是否已完成数据传送;1是) 和 seq(序列号,标识特定的本次连接u) 到服务器,客户端进入FIN_WAIT_1状态,等待服务器确认;
- 第二次握手:服务器收到连接请求,确认FIN标志位是1,即客户端发起了断开请求; 服务器发送__ACK(是否收到请求;1是) 和 ack(u+1,特定某次请求); seq(序列号,标识特定的本次连接v)__,客户端等待服务器处理数据,进入FIN_WAIT_2状态;
- 第三次握手:服务器传送完数据,向客户端发送__ACK(是否收到请求;1是) 和 ack(u+1,特定某次请求); FIN(是否已完成数据传送;1是) 和 seq(序列号,标识特定的本次连接w)__,此时服务器进入CLOSE_WAIT状态。
- 第四次握手:客户端收到服务器的断开请求,向服务器发送__ACK(是否收到请求;1是) 和 ack(w+1,特定某次请求); seq(序列号,标识特定的本次连接u+1)__,Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭。
次数 | 客户端状态 | 服务器状态 | 发送数据 |
---|---|---|---|
第一次握手 | FIN_WAIT_1 | FIN:标志位1; seq:序列号,随机数u | |
第二次握手 | FIN_WAIT_2 | 标志位ACK: 1; ack:确认号,u+1; seq:序列号,随机数v | |
第三次握手 | CLOSE_WAIT | 标志位ACK: 1; ack:确认号,u+1; 标志位FIN:1; seq:序列号,随机数w | |
第四次握手 | established | established | 标志位ACK: 1; ack:确认号,w+1; seq:序列号,u+1 |
总结:
1、server先关闭,client再关闭
2、状态:
FIN : finish
fin-wait
close-wait
为什么要四次挥手
那四次挥手又是为何呢?TCP协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP是全双工模式,
这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;
但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;
当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。
完整图
TCP协议的常见面试问题
为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
TCP 有超时重发机制。