TCP状态机介绍

在网络协议栈中,目前只有TCP提供了一种面向连接的可靠性数据传输。而可靠性,无非就是保证,我发给你的,你一定要收到。确保中间的通信过程中,不会丢失数据和乱序。在TCP保证可靠性数据传输的实现来看,超时重传、序列号及数据的应答 这三个特征 就是实现可靠性的最基本保证,而对于tcp窗口大小等等设置,也是保证可靠性的一个方面。所有的目的只为一个,保证传输数据的完整性。为了解决传输线路的不稳定性造成数据包的丢失情况,tcp 使用了发送方超时重传和接收方数据应答的策略。概括而言,就是一种“状态协议“,保证通信双方数据收发的一致性。

  1. TCP_CLOSE:关闭状态,一个新建的TCP socket 会处于该状态。
  2. TCP_LISTEN: 监听状态,一般服务器端套接字在调用Listen系统调用后即处于该状态。
  3. TCP_SYN_SENT:同步信号已经发送状态,这个状态一般是指客户端发送SYN(建立连接的同步)数据包后所处的状态(tcp三次握手的第一个包)。在接收到远端服务器端的应答后,即从该状态进入TCP_ESTABLISHED状态。
  4. TCP_SYN_RECEIVED:同步信号已经接受状态,服务器端在接受到远端客户端SYN数据包后,进行相应的处理(创建通信套接字等),然后发送应答数据包(tcp三次握手的第二个包),并将新创建的通信套接字状态设置为TCP_SYN_RECEIVED,在接受到客户端的应答后,即进入TCP_ESTABLISED状态。
  5. TCP_ESTABLISED:建立连接状态,这是双方进行正常通信所处的状态。
  6. TCP_FIN_WAIT_1:本地发送FIN(用于结束连接的)数据包后即可进入该状态,等待对方的应答。一般一端发送完其所要发送的数据后,即可发送FIN数据包,此时发送通道被关闭,但仍可继续接受远端发送的数据包。在接受到远端发送的对于FIN数据包的应答后,将进入TCP_FIN_WAIT_2状态。
  7. TCP_FIN_WAIT_2:进入该状态表示本地已经接受到远端发送的对于本地之前发送的FIN数据包的应答。进入该状态后,本地仍然可以继续接受远端发送给本地的数据包。在接受到远端发送的FIN数据包后(表示远端也已经发送完数据),本地将发送一个应答数据包,并进入TCP_TIME_WAIT状态。TCP_TIME_WAIT状态存在的时间被称为2MSL时间,这一方面是为避免本地发送的应答数据包丢失,另一方面避免一个新创建的套接字接收到旧套接字中遗留的数据包。
  8. TCP_TIME_WAIT:该转状态呗称为2MSL等待状态。如果在此期间接收到远端发送的FIN数据包,则表示之前在TCP_FIN_WAIT_2状态发送的ACK应答数据包在传输中丢失或者长时间被延迟,从而造成了远端重新发送了FIN数据包,此时重复ACK应答数据包。一旦2MSL时间到期,则将进入TCP_CLOSED状态,即完成关闭操作。
  9. TCP_CLOSE_WAIT:该状态存在于后关闭的一端。当接收到远端发送的FIN数据包后,本地发送一个ACK应答数据包,并将该套接字状态从TCP_ESTABLISED设置为TCP_CLOSE_WAIT。本地可以继续向远端发送数据包,在发送完所有的数据后,本地将发送一个FIN数据包关闭本地发送通道,并将状态设置为TCP_LAST_ACK状态,等待远端对FIN数据包的应答数据包。
  10. TCP_CLOSING:如果通信双方同时发送FIN数据包,则同时进行关闭操作,则双方将同时进入TCP_CLOSING状态。具体的,本地发送一个FIN数据包以结束本地数据包发送,如果在等待应答期间,接收到远端发送的FIN数据包,则本地将状态设置为TCP_CLOSING状态。在接收到应答后,再继续装入到TCP_CLOSE_WAIT状态。
  11. TCP_LAST_ACK:作为后关闭的一方,在发送FIN数据包后,即进入TCP_LAST_ACK状态。此时等待远端发送应答数据包,在接收到应答数据包后,即完成关闭操作,进入TCP_CLOSE状态。

三次握手

三次握手过程

三次握手过程是客户端主动向正在监听的服务发起交换序号、建立连接的过程,三次握手过程如下:

  1. 第一次握手
    客户端主动发送SYN包到服务器,其中包含客户端的初始序号seq=x,并进入SYN_SENT状态,等待服务器确认。(其中,SYN=1,ACK=0,表示这是一个TCP连接请求数据报文;序号seq=x,x是随机数,表明传输数据时的第一个数据字节的序号是x)。
  2. 第二次握手
    服务器收到请求后,必须确认客户的数据包,同时自己也发送一个SYN包,即SYN+ACK包,此时服务器进入SYN_RECV状态。(其中确认报文段中,标识位SYN=1,ACK=1,表示这是一个TCP连接响应数据报文,并含服务端的初始序号seq=y,y是随机数,以及服务器对客户端初始序号的确认号ack(服务器)=seq(客户端)+1=x+1)。
  3. 第三次握手
    客户端收到服务器的SYN+ACK包,向服务器发送确认包(seq=x+1,ack=y+1),此包发送完毕,客户端和服务器进入ESTAB_LISHED(TCP连接成功)状态,完成三次握手。

三次握手交换各自的序号,建立起连接。

握手过程为什么是三次而不是两次、四次?

TCP作为一种可靠传输控制协议,其核心思想:既要保证数据可靠传输,又要提高传输的效率,而用三次恰恰可以满足以上两方面的需求!

为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤

两次握手的场景

两次握手过程其实只有三次握手的前两次握手,没有第三次握手

两次握手至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。

想象一个场景,client向server发送一个连接请求,由于一些原因,导致client发出的连接请求在一个网络节点逗留了比较多的时间。此时client会将此连接请求作为无效处理 又重新向server发起了一次新的连接请求,server正常收到此连接请求后建立了连接,数据传输完成后释放了连接。如果此时client发出的第一次请求又到达了server,server会以为client又发起了一次连接请求。如果是两次握手:此时连接就建立了,server会维持连接一直等待client发送数据,从而白白浪费server的资源。 如果是三次握手:由于client没有发起连接请求,也就不会理会server的连接响应,server没有收到client的确认连接,就会关闭掉本次连接。如果第一次握手大量延时或者第二次握手大量丢失 ,就会造成“SYN的洪水攻击”效果。

四次握手的场景

四次握手其实就是将第二次握手发送ACK与SYN分开进行,这样子有违高效的原则。

序列号与确认号

  • wireshark中序列号默认显示相对序列号,序列号是从0开始,实际序列号是在三次握手过程双方随机选取的。可以通过设置来显示真实的序列号,【编辑】->【首选项】->【Protocols】->【TCP】->【Relative sequence numbers(Requires “Analyer TCP sequence numbers”)】复选框去掉
  • 通过流量图来分析序列号与确认号。【统计】->【流量图】->【流类型】选择【TCP Flows】

通过HTTP请求的TCP流量图分析序列号与确认号

  1. 第一次握手,client发送SYN包请求建立TCP连接,初始化序列号seq = 4129057982,随机生成的, 确认号ack = 0,一般都是0;
  2. 第二次握手,server对请求进行确认,ack = 4129057982 + 1(SYN虽没负载数据,但消耗一个序列号),同时进行SYN,seq = 4200111240(随机)
  3. 第三次握手,client对server的SYN包发送ACK包,ack = 4200111240 + 1,seq = 4129057983
  4. 第四个包,client发送负载725字节的HTTP请求包,seq = 4129057983(注意ACK没有消耗seq序号,跟第三次握手的seq一样), ack = 4200111241
  5. 第五个包,server响应tcp确认包,seq = 4200111241, ack = 4129057983 + 725 = 4129058708

四次挥手

四次挥手主要是关闭tcp建立起来的连接,释放相关资源

四次挥手过程

在实际应用中,客户端主动关闭到服务器的连接,服务器在检测到客户端关闭连接后,关闭对应的连接。

  • 第一次挥手: 客户端发送一个FIN,用来关闭客户端到服务器的数据传送服务器的确认。其中终止标志位FIN=1,序列号seq=u.
  • 第二次挥手: 服务器收到这个FIN,它发送一个ACK,确认ack为收到的序号加一。
  • 第三次挥手: 关闭服务器到客户端的连接,发送一个FIN给客户端。
  • 第四次挥手: 客户端收到FIN后,并发回一个ACK报文确认,并将确认序号seq设置为收到序号加一。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

客户端发送FIN后,进入终止等待状态,服务器收到客户端连接释放报文段后,就立即给客户端发送确认,服务器就进入CLOSE_WAIT状态,此时TCP服务器进程就通知高层应用进程,因而从客户端到服务器的连接就释放了。此时是“半关闭状态”,即客户端不可以发送给服务器,服务器可以发送给客户端。
此时,如果服务器没有数据报发送给客户端,其应用程序就通知TCP释放连接,然后发送给客户端连接释放数据报,并等待确认。客户端发送确认后,进入TIME_WAIT状态,但是此时TCP连接还没有释放,然后经过等待计时器设置的2MSL后,才进入到CLOSED状态。

2.为什么需要2MSL时间?
首先,MSL即Maximum Segment Lifetime,就是最大报文生存时间,是任何报文在网络上的存在的最长时间,超过这个时间报文将被丢弃。《TCP/IP详解》中是这样描述的:MSL是任何报文段被丢弃前在网络内的最长时间。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒、1分钟、2分钟等。

TCP的TIME_WAIT需要等待2MSL,当TCP的一端发起主动关闭,三次挥手完成后发送第四次挥手的ACK包后就进入这个状态,等待2MSL时间主要目的是:防止最后一个ACK包对方没有收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可以继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。

3.为什么是四次挥手,而不是三次或是五次、六次?
双方关闭连接要经过双方都同意。所以,首先是客服端给服务器发送FIN,要求关闭连接,服务器收到后会发送一个ACK进行确认。服务器然后再发送一个FIN,客户端发送ACK确认,并进入TIME_WAIT状态。等待2MSL后自动关闭。

总结:
(1)为了保证客户端发送的最后一个ACK报文段能够到达服务器。即最后一个确认报文可能丢失,服务器会超时重传,然后服务器发送FIN请求关闭连接,客户端发送ACK确认。一个来回是两个报文生命周期。

如果没有等待时间,发送完确认报文段就立即释放连接的话,服务器就无法重传,因此也就收不到确认,就无法按步骤进入CLOSED状态,即必须收到确认才能close。
(2)防止已经失效的连接请求报文出现在连接中。经过2MSL,在这个连续持续的时间内,产生的所有报文段就可以都从网络消失。

参考

  • TCP状态机-状态解析
  • TCP 为什么三次握手而不是两次握手(正解版)
  • TCP 为什么是三次握手,而不是两次或四次?
  • TCP为什么是三次握手和四次挥手
  • SDN手册

tcp状态机-三次握手-四次挥手以及常见面试题相关推荐

  1. 在深谈TCP/IP三步握手四步挥手原理及衍生问题—长文解剖IP

    如果对网络工程基础不牢,建议通读<细说OSI七层协议模型及OSI参考模型中的数据封装过程?> 下面就是TCP/IP(Transmission Control Protoco/Interne ...

  2. 再深谈TCP/IP三步握手四步挥手原理及衍生问题—长文解剖IP

    转载地址: https://www.zhoulujun.cn/html/theory/ComputerScienceTechnology/network/2015_0708_65.html 如果对网络 ...

  3. tcp 二次握手时延_一篇搞懂TCP的三次握手 四次挥手

    TCP的三次握手四次挥手,估计大家都听过.但是真的能把每一步说明白的人比较少.我还记得在之前面试的时候被面试官一顿问,然后一脸懵B... 都是大学没好好上课 ,这篇文章就跟大家讲讲到底这三握四挥是在搞 ...

  4. HTTP HTTPS WEB的cookie机制 TCP UCP(三次握手四次挥手)

    1.HTTP 与 HTTPS 的区别 理解: 1.HTTPS 协议需要到 CA (Certificate Authority,证书颁发机构)申请证书,一般免费证书较少,因而需要一定费用.(以前网易官网 ...

  5. 计算机网络之UDP与TCP协议(三次握手, 四次挥手)

    ⭐️前面的话⭐️ 本文介绍计算机网络中有关传输层协议的知识--UDP与TCP协议,在TCP协议中,为了保证数据的可靠传输,引入了十大保证可靠性的机制,即确认应答,超时重传,连接管理(三次握手,四次挥手 ...

  6. java tcp 三次握手_用Java代码分析TCP的三次握手四次挥手过程

    (1)客户端发送一个带SYN标志的TCP报文到服务器.这是三次握手过程中的报文1. (2) 服务器端回应客户端的,这是三次握手中的第2个报文,这个报文同时带ACK标志和SYN标志.因此它表示对刚才客户 ...

  7. 了解TCP协议,IP协议、ICMP协议和ARP协议(TCP报文,TCP的分成管理,TCP与UDP,TCP的三次握手四次挥手原理)

    文章目录 了解TCP/IP协议 TCP报文格式 TCP/IP 的分层管理 TCP与UDP TCP的三次握手与四次挥手 为什么要三次握手? 为什么要四次挥手? IP数据包格式 ICMP协议 ICMP协议 ...

  8. TCP的三次握手和四次挥手及常见面试题

    一.前言 今天上掘金查看热门文章,发现一篇好文 ★前端 100 问:能搞懂 80% 的请把简历给我 ★ ,此文包含100个前端面试问题,仔细阅读完所有题目后,顿感身中数刀无法呼吸,留下了没有技术的泪水 ...

  9. 计算机网络 —— TCP的三次握手四次挥手

    TCP的6个标志位 SYN -- synchronous :建立联机. ACK -- acknowledgement :确认. PSH -- push :传输. FIN -- finish :结束. ...

最新文章

  1. Python爬虫项目--爬取某宝男装信息 附带源码
  2. “大数据系统软件国家工程实验室”建设项目通过验收
  3. Leetcode 62.不同路径 (每日一题 20210701)
  4. android 数组赋值字符串_c语言中的字符数组与字符串
  5. Redis快的原因:线程切换 IO 内存 数据结构 VM机制
  6. 通过Spring集成进行消息处理
  7. Java集合(7):散列与散列码
  8. Linux shell sed awk
  9. Redis桌面客户端 Redis Studio
  10. RabbitMq学习笔记006---修改RabbitMq端口号和心跳时间
  11. C++ #include头文件随想
  12. Atiitt attilax掌握的前后技术放在简历里面.docx
  13. 小区广播机制(MIB、SIB)
  14. 前端面试及答案:boder实现0.5像素的方法
  15. 还在到处找Linux内核的学习资料吗?你想要的都在这里
  16. 【Linux】gcc编译工具,断点的设置,gdb调试
  17. iOS下86版五笔输入法练习程序(作为备忘,最基本功能的演示demo,版本:0.99版)
  18. 《强化学习与最优控制》学习笔记(一):确定性动态规划和随机性动态规划
  19. 【论文笔记】Bullseye Polytope: A Scalable Clean-Label Poisoning Attack with Improved Transferability
  20. 例一---骨骼肌肉模型简介

热门文章

  1. python tkinter下载器_下载小说还要去找网站?Python使用tkinter打造一个小说下载器...
  2. 嵌入式操作系统_航天科工海鹰翼辉嵌入式操作系统获自主原创“身份证”
  3. wrapper怎么用_用责任链模式设计拦截器
  4. JAVA入门级教学之(方法-7)
  5. .jar文件如何打开_ofd发票文件如何打开
  6. 多帧点云数据拼接合并_PCL点云处理实践(二):点云的处理和拼接
  7. try catch php 捕获,php try catch : 捕捉异常,抛出异常
  8. 经典Java编程面试题分析
  9. 微型计算机的alu部件是包含在,微型计算机的ALU部件是什么?
  10. python 实现显著性检测_强!汽车车道视频检测:python+OpenCV为主实现