TCP的三次握手和四次挥手
TCP/IP 协议在计算机网络中是非常重要的部分,本文主要是简单介绍其中的 TCP 协议和 IP 协议,也会涉及一些在面试中经常遇到的问题。
TCP/IP 协议
在最项目开发中,经常会遇到各种协议,互联网基础通信框架就是 TCP/IP。TCP/IP 是个协议族,可分为四个层次:网络接口层(连接层)、网络层、传输层和应用层。
可以这样理解它们的作用:
- 连接层负责建立电路连接,是整个网络的物理基础,典型的协议包括以太网、Wi-Fi、MPLS 等;
- 网络层负责分配地址和传送二进制数据,主要协议是IP协议,也有 ICMP 协议、ARP 协议、RARP 协议和 BOOTP 协议;
- 传输层负责传送文本数据,主要协议是 TCP 协议与 UDP 协议;
- 应用层负责传送各种最终形态的数据,是直接与用户打交道的层,典型协议是 FTP、HTTP、TELNET、SMTP、DNS 等。
TCP协议
特点
- TCP提供一种面向连接的、可靠的字节流服务
- 在一个TCP连接中,仅有两方进行彼此通信。广播和多播不能用于TCP
- TCP使用校验和,确认和重传机制来保证可靠传输
- TCP使用累积确认
- TCP使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制
三次握手
所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。
TCP 连接三次握手四次挥手(下小节介绍)如下图所示(图片来自简析TCP的三次握手与四次分手)
- 第一次握手:建立连接
- 客户端发送连接请求报文段,将
SYN
位置为1,Sequence Number
为x
; - 然后,客户端进入
SYN_SEND
状态,等待服务器的确认;
- 客户端发送连接请求报文段,将
- 第二次握手:服务器收到
SYN
报文段- 服务器收到客户端的
SYN
报文段,需要对这个SYN
报文段进行确认,设置Acknowledgment Number
为x+1
(Sequence Number+1
); - 同时,自己自己还要发送
SYN
请求信息,将SYN
位置为1,Sequence Number
为y
;服务器端将上述所有信息放到一个报文段(即SYN+ACK
报文段)中,一并发送给客户端,此时服务器进入SYN_RECV
状态;
- 服务器收到客户端的
- 第三次握手:客户端收到服务器的
SYN+ACK
报文段- 将
Acknowledgment Number
设置为y+1
,向服务器发送ACK
报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED
状态,完成 TCP 三次握手。
- 将
完成了三次握手,客户端和服务器端就可以开始传送数据。
为什么需要三次握手
既然总结了TCP的三次握手,那为什么非要三次呢?怎么觉得两次就可以完成了。那TCP为什么非要进行三次连接呢?在谢希仁的《计算机网络》中是这样说的:
为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
在书中同时举了一个例子,如下:
“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”
这就很明白了,防止了服务器端的一直等待而浪费资源。
四次挥手
示意图如上图所示。
当客户端和服务器通过三次握手建立了 TCP 连接以后,当数据传送完毕,肯定是要断开 TCP 连接的,这时候 TCP 采用的是四次挥手。
- 第一次挥手
- 主机1(可以使客户端,也可以是服务器端),设置
Sequence Number
和Acknowledgment Number
,向主机2发送一个FIN
报文段; - 此时,主机1进入
FIN_WAIT_1
状态;这表示主机1没有数据要发送给主机2了;
- 主机1(可以使客户端,也可以是服务器端),设置
- 第二次挥手
- 主机2收到了主机1发送的
FIN
报文段,向主机1回一个ACK
报文段,Acknowledgment Number
为Sequence Number
加1; - 主机1进入
FIN_WAIT_2
状态; - 主机2告诉主机1,我“同意”你的关闭请求;
- 主机2收到了主机1发送的
- 第三次挥手
- 主机2向主机1发送
FIN
报文段,请求关闭连接; - 同时主机2进入
LAST_ACK
状态;
- 主机2向主机1发送
- 第四次挥手
- 主机1收到主机2发送的
FIN
报文段,向主机2发送ACK
报文段,然后主机1进入TIME_WAIT
状态; - 主机2收到主机1的
ACK
报文段以后,就关闭连接; - 此时,主机1等待 2MSL 后依然没有收到回复,则证明 Server 端已正常关闭,那好,主机1也可以关闭连接了。
- 主机1收到主机2发送的
为什么需要四次挥手
那四次分手又是为何呢?TCP 协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP 是全双工模式,这就意味着,当主机1发出 FIN
报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回 ACK
报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了 FIN
报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次 TCP 连接。如果要正确的理解四次分手的原理,就需要了解四次分手过程中的状态变化。
FIN_WAIT_1
: 这个状态要好好解释一下,其实FIN_WAIT_1
和FIN_WAIT_2
状态的真正含义都是表示等待对方的FIN
报文。而这两种状态的区别是:FIN_WAIT_1
状态实际上是当 SOCKET 在ESTABLISHED
状态时,它想主动关闭连接,向对方发送了FIN
报文,此时该 SOCKET 即进入到FIN_WAIT_1
状态。而当对方回应ACK
报文后,则进入到FIN_WAIT_2
状态,当然在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK
报文,所以FIN_WAIT_1
状态一般是比较难见到的,而FIN_WAIT_2
状态还有时常常可以用netstat
看到。(主动方)FIN_WAIT_2
:上面已经详细解释了这种状态,实际上FIN_WAIT_2
状态下的 SOCKET,表示半连接,也即有一方要求 close 连接,但另外还告诉对方,我暂时还有点数据需要传送给你(ACK
信息),稍后再关闭连接。(主动方)CLOSE_WAIT
:这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方 close 一个 SOCKET 后发送FIN
报文给自己,你系统毫无疑问地会回应一个ACK
报文给对方,此时则进入到CLOSE_WAIT
状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close 这个 SOCKET,发送FIN
报文给对方,也即关闭连接。所以你在CLOSE_WAIT
状态下,需要完成的事情是等待你去关闭连接。(被动方)LAST_ACK
: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN
报文后,最后等待对方的 ACK 报文。当收到 ACK 报文后,也即可以进入到CLOSED
可用状态了。(被动方)TIME_WAIT
: 表示收到了对方的FIN
报文,并发送出了 ACK 报文,就等 2MSL 后即可回到CLOSED
可用状态了。如果FINWAIT1
状态下,收到了对方同时带FIN
标志和 ACK 标志的报文时,可以直接进入到TIME_WAIT
状态,而无须经过FIN_WAIT_2
状态。(主动方)CLOSED
: 表示连接中断。
TCP 重传机制
这部分可以参考TCP 的那些事儿(下)一文。
SYN攻击
什么是 SYN 攻击(SYN Flood)?
在三次握手过程中,服务器发送 SYN-ACK
之后,收到客户端的 ACK
之前的 TCP 连接称为半连接(half-open connect)。此时服务器处于 SYN_RCVD
状态。当收到 ACK 后,服务器才能转入 ESTABLISHED
状态.
SYN 攻击指的是,攻击客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送 SYN
包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的 SYN
包将长时间占用未连接队列,正常的 SYN
请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。
SYN
攻击是一种典型的 DoS/DDoS
攻击。
如何检测 SYN 攻击?
检测 SYN
攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次 SYN
攻击。在 Linux/Unix 上可以使用系统自带的 netstats
命令来检测 SYN
攻击。
如何防御 SYN 攻击?
SYN
攻击不能完全被阻止,除非将 TCP 协议重新设计。我们所做的是尽可能的减轻 SYN
攻击的危害,常见的防御 SYN
攻击的方法有如下几种:
- 缩短超时(SYN Timeout)时间
- 增加最大半连接数
- 过滤网关防护
- SYN cookies技术
常见面试题
TCP 与 UDP 的区别?
- TCP是面向连接的、可靠的、有序的、速度慢的协议;UDP是无连接的、不可靠的、无序的、速度快的协议。
- TCP开销比UDP大,TCP头部需要20字节,UDP头部只要8个字节。
- TCP无界有拥塞控制,TCP有界无拥塞控制。
补充:
- 基于TCP的协议有:HTTP/HTTPS,Telnet,FTP,SMTP。
- 基于UDP的协议有:DHCP,DNS,SNMP,TFTP,BOOTP。
TCP | UDP | |
---|---|---|
特点 | 面向连接;可靠;开销大 | 无连接;不可靠;效率高;可靠性由应用层负责 |
三次握手过程及其原因
如上面所述
四次挥手及其原因
如上面所述
TCP 拥塞控制
这部分可以参考TCP 的那些事儿(下)一文。
参考:
公众号
个人公众号(柳年思水)已经上线,最新文章会同步在公众号发布,欢迎大家关注~