一、TCP分层
TCP/IP协议是Internet互联网中最基本的协议,其在一定程度上参考了OSI七层模型,但在TCP/IP协议中,七层被简化成了四层,如下:
OSI模型 | TCP/IP协议 | |
第七层 | 应用层 | 应用层 HTTP/FTP/SMTP/Telnet |
第六层 | 显示层 | |
第五层 | 会话层 | |
第四层 | 传输层 | 传输层 TCP/UDP |
第三层 | 网络层 | 网络层 ICMP、IP、IGMP、ARP、RARP |
第二层 | 数据链路层 | 链路层 各种物理通信网络接口 |
第一层 | 物理层 |
(1)TCP/IP协议的应用层
应用层的协议主要有HTTP(万维网服务)、FTP(文件传输)、SMTP(电子邮件)、SSH(安全远程登录)、DNS(域名解析)、Telnet等,是用于读取来自传输层的数据或者将数据写入传输层。
应用层包括所有和应用程序协同工作,并利用基础网络交换应用程序的业务数据的协议。一些特定的程序被认为运行在这个层上,该层协议所提供的服务能直接支持用户应用。
(2)TCP/IP协议的传输层
传输层的主要协议有UDP(用户数据协议)、ICP(传输控制协议)等,实现端到端的数据传输。
传输层的协议,解决了诸如端到端可靠性问题,能确保数据可靠的到达目的地,甚至能保证数据按照正确的顺序到达目的地。传输层的主要功能大致如下:
- 为端到端连接提供传输服务;
- 这种传输服务分为可靠和不可靠,其中TCP是典型的可靠传输,UDP则是不可靠传输;
- 为端到端连接提供流量控制、差错控制、QoS(Quality of Service)服务质量等管理服务。
TCP协议是一个面向连接的、可靠的传输协议,它提供一种可靠的字节流,能保证数据完整、无损并且按照顺序达到。TCP尽量连续不断地测试网络的负载并且控制发送数据的速度以避免网络过载。另外,TCP试图将数据按照规定的顺序发送。
UDP协议是一个无连接的数据报协议,是一个“尽力传递”和“不可靠”协议,不会对数据包是否已经达到目的地进行检查,并且不保证数据包按顺序达到。
总体来说,TCP协议传输效率低,但可靠性强;UDP协议传输效率高,但可靠性略低,适用于传输可靠性要求不高、体量小的数据(如QQ聊天数据)、
(3)TCP/IP协议的网络层
网络层的协议主要有ICMP、IP、IGMP等。
TCP/IP协议的网络层的作用是在复杂的网络环境中为要发送的数据报找到一个合适的路径进行传输。简单来说,网络层负责将数据传输到目标地址,目标地址可以是多个网络通过路由器连接而成的某一个地址。另外,网络层负责寻找合适的路径达到对方的计算机,并将数据帧传送给对方,网络层还可以实现拥塞机制、网际互连等功能。
(4)TCP/IP协议的链路层
链路层的主要协议有ARP、RARP等。
链路层有时也称作数据链路层或网络接口层,用来处理连接网络的硬件部分。该层既包括操作系统硬件的设备驱动、NIC(网卡)、光纤物理可见部分,还包括连接器等一切传输媒介。在这一层,数据的传输单位为比特。
二、TCP建立连接时的三次握手
TCP建立连接时,双方要经过三次握手过程,具体如下:
- 第一次握手:Client进入SYN_SENT状态,发送一个SYN帧来主动打开传输通道,该帧的SYN标志位被设为1,同时会带上Client分配好的序列号SN,该SN是根据时间产生的一个随机值,通常情况下每间隔4ms会加1。除此之外,SYN帧还会带一个MSS(最大报文段长度)可选项的值,表示客户端发送出去的最大数据块的长度;
- 第二次握手:Server在收到SYN帧后,会进入SYN_RCVD状态,同时返回SYN+ACK帧给Client,主要目的在于通知Client已经收到SYN消息,现在需要进行确认。Server发出的SYN+ACK帧的标志位被设置为1、其确认序列号AN值被设置为SN+1(此处的SN为Client的序号)、SN是Server产生的序列号;
- 第三次握手:Client在收到Server的第二次握手SYN+ACK确认帧之后,首先状态会从SYN_SENT变成ESTABLISHED,表示自己方向的连接通道已经建立成功,Client可以发送数据给Server,然后Client发送ACK帧给Server,该ACK得标志位被设置为1,确认序列号AN值被设置为SN+1(此处的SN为Server的序号),SN序号为第一次握手时Client产生的SN+1。
简化理解三次握手过程:
- 第一次握手,客户端发送连接请求报文段:连接请求报文不携带数据,但要消耗一个序号。发送内容包括:SYN=1,SN=x(随机值);
- 第二次握手,服务端为该TCP连接分配缓存和变量,并向客户端返回确认字段,允许连接:确认请求报文不携带数据,但要消耗一个序号。发送内容包括:SYN=1,ACK=1,SN=y(随机值),AN=x+1;
- 第三次握手,客户端为该TCP连接分配缓存和变量,并向服务端返回确认的确认:可以携带数据。发送内容包括:SYN=1,ACK=1,SN=x+1,AN=y+1。
三、TCP断开连接时的四次挥手
TCP断开连接时,双方要经过四次挥手过程,在这个过程中,每个连接端都能主动地、独立地发起断开请求,具体如下:
- 第一次挥手:主动断开方(可以是客户端,也可以是服务端)向被动断开方发送一个FIN结束请求报文,此报文的FIN位被设置为1,ACK为1,且正确设置SN=x。主动断开方进入FIN_WAIT_1状态,表示主动断开方没有数据要发送,但还能接收数据。
- 第二次挥手:被动断开方在收到FIN断开请求后,向主动断开方发送一个ACK响应报文,ACK=1,AN=x+1,SN=y,之后被动断开方进入CLOSE_WAIT状态;
- 第三次挥手:收到被动断开方发送的ACK之后,主动断开方会从FIN_WAIT_1变为FIN_WAIT_2。被动断开方在发送完ACK报文后,继续完成业务数据的传送,当数据全部传送完毕后,被动断开方会向主动断开方发送FIN+ACK结束响应报文,表示数据已经全部发送完了,被动断开方进入LAST_WAIT状态;
- 第四次挥手:主动断开方在收到FIN+ACK之后,还需要进行最后的确认,向被动断开方发送一个ACK报文,然后,主动断开方进入TIME_WAIT状态,等待超时(等待2*MSL的时间,如果期间没有收到其他报文,则证明对方已经正常关闭)后最终关闭连接。被动断开方在收到主动断开方发送的ACK之后,关闭连接。
简化理解四次挥手过程:
- 第一次挥手,主动断开方发出断开请求:FIN=1,ACK=1,SN=x;
- 第二次挥手,被动断开方收到请求并确认 :ACK=1,SN=y,AN=x+1;
- 第三次挥手,被动断开方传送完数据,发送结束响应报文:FIN=1,ACK=1,SN=z,AN=x+1;
- 第四次挥手,主动断开方进行最后确认:ACK=1,SN=x+1,AN=z+1;等待2*MSL,最终关闭。
四、三次握手和四次挥手中的系列问题
4.1、握手丢失
注意:ACK报文是不会有重传的,当ACK丢失,就由对方重传对应的报文。
(1)丢失第一次握手
第一次握手是客户端向服务端发送SYN报文,然后进入SYN_SENT状态。
丢失第一次握手,客户端一直收不到服务端的SYN+ACK,就会触发超时重传机制,重传SYN报文。
注意:客户端SYN最大重传次数是由tcp_syn_retries内核参数控制,这个参数可以自定义,默认为5。
通常情况下,第一次超时重传是在1秒后,第二次是在2秒后,第三次是在4秒后,第四次是在8秒后,第五次是在16秒后。当第五次重传后,会继续等待32秒,若仍未得到服务端的回应,客户端就不再发送SYN报文,且断开TCP连接。
(2)丢失第二次握手
第二次握手是服务端在收到客户端发送的SYN报文后,返回给客户端的SYN+ACK报文,服务端的状态变为SYN_RCVD。
丢失第二次握手时,客户端收不到服务端的回应,会以为是自己的SYN报文丢失,所以会触发超时重传机制,重发SYN报文;在此同时,服务端也收不到客户端的ACK确认报文,服务端也会触发超时重传机制,重传SYN+ACK报文。
注意:SYN+ACK报文最大重传次数是由tcp_synack_retries内核参数决定,默认为5。
(3)丢失第三次握手
第三次握手是客户端向服务端发送ACK报文,客户端状态变为ESTABLISHED状态。
因为ACK报文不会重传,所以第三次丢失后,服务端迟迟收不到确认报文,就会触发超时重传机制,重传SYN+ACK报文。
4.2、挥手丢失
(1)丢失第一次挥手
第一次挥手是主动断开方向被动断开方发送FIN请求断连的报文,且主动断开方状态会变为FIN_WAIT_1。
正常情况下,主动方会受到被动方的ACK报文,然后改变状态到FIN_WAIT_2,若第一次挥手丢失,客户端就会迟迟收不到ACK报文,触发超时重传机制,重传FIN报文,最大重传次数由tcp_orphan_retries参数控制。当达到最大重传次数仍未收到ACK确认报文时,主动方不再发送FIN报文,会直接进入close状态。
(2)丢失第二次挥手
第二次挥手是被动方给主动方的ACK确认报文,被动方进入CLOSE_WAIT状态。
丢失第二次挥手,又由于ACK报文不会重传,所以主动方会触发超时重传机制,重传FIN报文。
(3)丢失第三次挥手
第三次挥手是被动方在传送完数据后向主动方发送的FIN报文,被动方状态变为LAST_ACK。
主动方在收到第二次挥手时由被动方发送的确认报文ACK后,会变为FIN_WAIT_2状态,此状态有限制时间,默认为60秒,若60秒后还未收到FIN报文,主动方就会直接关闭连接。
被动方在发送FIN后,期待能收到主动方发送的ACK,若被动方迟迟未收到ACK,就会触发超时重传机制,重传FIN报文。
(4)丢失第四次挥手
第四次挥手是主动方向被动方发送ACK确认报文,且主动方状态变为TIME_WAIT。
被动方迟迟未收到ACK时,会触发超时重传机制,重传FIN报文,且在未收到ACK之前,状态一直为LAST_ACK。
4.3、为什么断连是四次挥手,而连接是三次握手?
原本握手也是四次,如下:
- 第一次握手:客户端向服务端发送SYN=1,SN=x;
- 第二次握手:服务端向客户端发送ACK=1,AN=x+1;
- 第三次握手:服务端向客户端发送SYN=1,SN=y;
- 第四次握手:客户端向服务端发送ACK=1,SYN=1,SN=x+1,AN=y+1。
TCP是全双工通信,上面四步保证了两个方向上都是可以正确到达的,因为第二次握手和第三次握手没有上下的联系,于是将两步合为一步,加快握手效率,变为了三次握手。
4.4、为什么第四次挥手后主动断开方要等待2*MSL的时间?
MSL是指Maximum Segment Lifetime,意为报文的最大生存时间,超过这个时间,报文就会被丢弃。
①主动方等待2*MSL的时间,是为了确保两端都能最终关闭。假如主动方不等待而是在接收到被动方发送的FIN后立即释放,而第四次挥手又丢失,此时被动方收不到ACK触发超时重传,重传了FIN给主动方,但主动方已经无法接收被动方重传的FIN,也就无法再发送一次ACK报文,这样就导致被动方无法进入CLOSED状态。
②防止历史连接中的数据出现在新连接中。主动方在发送完ACK后进入TIME_WAIT状态,经过2*MSL后才能最终关闭和释放端口,就意味着,相同端口的新TCP连接需要在2*MSL后才能够正常的建立,在2*MSL这段时间内,旧连接所产生的所有数据报文都从网络中消失,避免了影响新的连接。
4.5、若已经建立好连接,Client端出现故障,会发生什么?
TCP中设有一个保活计时器,Client端若出现故障,Server端不会一直等下去。Server在每次收到Client数据帧后,保活计时器会复位,超时时间通常设置为2小时(可以自行调整),若2小时内未收到任何Client的数据帧,Server就会发送一个探测报文段,之后每隔75秒发送一次,若连发10个探测报文段仍没反应,Server就会认为Client出现故障,关闭连接。