TCP协议同样是运输层的协议,掌握TCP重点要关注这几个问题:顺序问题、丢包问题、连接维护、流量控制、拥塞控制。先解析下TCP报文段结构,相比于UDP要复杂很多。

  • 首先还是两个端口号,对应着具体的应用进程。
  • 序号指的是包的序号,为了解决包乱序问题。
  • 发出去的包应该有确认,如果接收方没有收到就应该重新发送,直到送达。确认序号解决的是丢包问题。
  • 由于TCP选项字段的原因,TCP首部长度是可变的。通常选项字段为空,所以TCP首部字段长度一般是20字节。
  • 窗口大小用于流量控制,用来指示接收方愿意接收的字节数量。
  • 选项字段用于发送方与接收方协商最大报文段长度或者在高速网络环境下用作窗口调节因子。
  • 标志字段由6个状态位组成,SYN是发起一个连接、ACK是回复、RST是重新连接、FIN是结束连接。URG表示报文段里存在着被发送端的上层实体置为“紧急” 的数据,紧急数据的最后一个字节由16b位的紧急数据指针字段指出。实际使用中,PSH、URG和紧急数据指针用不到。

所有的问题起于连接,先关注连接管理问题。TCP的连接建立分为三步,通常称为三次握手。具体的的状态是:

客户端收到服务端发送的 SYN 和 ACK 之后,发送ACK 的 ACK,之后处于 ESTABLISHED 状态,因为它一发一收成功了。服务端收到 对ACK 的 ACK 之后,处于 ESTABLISHED 状态,因为它也一发一收了。

为什么不是两次、四次或者更多次?

  比如AB要建立连接,A发起一个连接但连接请求没有响应,可能包丢了、包绕弯路了、超时了等等,A于是继续给B发包,终于B收到了请求包但A并不知道,所以A可能还会继续发。B收到包之后,知道了A存在并且要和它建立连接。如果B不想建立连接,A重试一会后放弃,连接建立失败没有问题。如果B愿意建立连接,那就会发应答包给A。同样这个应答包会和请求包出现一样的问题,那么对于B不能认为连接建立好了。

  B发送的应答包可能会发送多次,只要有一次到达A,那么A就认为连接已经建立了,因为A的消息有去有回,相当于两次握手。假如这时候连接已经建立,并且做了简单通信后,结束了连接。上面讲了A要建立连接的时候,可能会发送多个请求包。有的请求包绕了一大圈又回来了,B 会认为这也是一个正常的的请求,再次建立连接,但这个连接不会正常接发数据、也不会终结,B就一直等待。A发的消息有去有回,但B发出的消息没有回,所以两次握手肯定不行。其实三次握手中,A发给B回复的回复也会丢、绕路或者B挂了,按照这个逻辑B还要再发个确认就变成了四次握手,这样不停套娃多达几百次也可以,但这也不能保证就可靠了。TCP连接的设计原则是双发的消息都有去有回就基本可以了。

  大部分情况下,A和B建立连接后会A会马上发送数据,如果A发给B的应答丢了,A后续发送的数据到达时,B可以认为连接已经建立;又或者B挂了,那么直接报错返回B不可达信息都没问题。如果A就是不发送数据,客户端可以开启keeplive机制,发送探活包。服务端设置规定时间,超时了就主动关闭,释放资源。

  TCP把数据看成一个无结构、有序的字节流,一个报文段的序号是该报文段首字节的字节流编号。三次握手除了确保双方消息有去有回,最重要的是解决tcp包的序号问题。A、B双方互相告知对方包的起始序号。又会有个疑问,为什么一定要交换序号,不能从序号1开始发包吗?假设A给B发3个包,序号为1、2、3,但3包可能绕路了,没有正常到达B,A又重新发送。后来A掉线了,重新连上B后又从1开始,发送两个包1、2,但上次出问题的包3又回来了,发给了B,B认为这就是A要发给它的下一个包,于是出现错误。因此每个连接都要有不同的序号,序号的起始序号每4ms加一,等遇到重复的序号要4个多小时。比如3号包绕路了,就要隔4个多小时连接的起始序号才是3,这么长时间3号包已经无效了,因为IP包头里有TTL(生存时间)。

再来看四次挥手,前两次和握手连接差不多。同样将发送接收方用AB表示。当B进入CLOSED-WAIT,A进入FIN-WAIT2状态时,如果B突然挂了,那么A会一直处于这个状态,TCP本身没有对这种个状态进行处理。在Linux中可以调整 tcp_fin_timeout 参数,设置超时时间。

  如果一切正常,进行第三次挥手A收到B的主动关闭请求并发送确认后进入TIME-WAIT状态,为什么需要这个状态呢?假设A发送完确认消息后直接关闭,如果B没收到这个确认消息,那B会重发结果就是B关闭失败。还有一种情况是A的端口空出来,但B还保持原来状态不知道A的情况。如果 A 的端口被一个新的应用占用了,这个新的应用会收到上个连接中 B 发过来的包,数据接收错误。所以A要进入TIME-WAIT状态,并且TCP设置了等待时间2MSL(报文段最大生存时间),任何报文在网络上存在超过这个时间将被丢弃。协议规定 MSL 为 2 分钟,实际应用中常用的是 30秒,1 分钟和 2 分钟等。还有一种情况是超过了2MSL,B依然没有收到对FIN的ACK。这时即便A收到了B重发的FIN,A会直接发送RST,表示重新开始挥手。

参考资料:《趣谈网络协议》刘超

     《计算机网络:自顶向下方法》原书第六版 陈鸣译

详解TCP一:三次握手、四次挥手的更多相关文章

  1. 详解 TCP的三次握手四次挥手

    本文转载来自https://blog.csdn.net/qzcsu/article/details/72861891 背景描述 通过上一篇中网络模型中的IP层的介绍,我们知道网络层,可以实现两个主机之 ...

  2. 端口状态 LISTENING、ESTABLISHED、TIME_WAIT及CLOSE_WAIT详解,以及三次握手四次挥手,滑动窗口(整理转发)

    网上查了一下端口状态的资料,我下面总结了一下,自己学习学习: TCP状态转移要点 TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于假死 ...

  3. 详解TCP的三次握手四次断开

    本文将分别讲解经典的TCP协议建立连接(所谓的“3次握手”)和断开连接(所谓的“4次挥手”)的过程. 尽管TCP和UDP都使用相同的网络层(IP),TCP却向应用层提供与UDP完全不同的服务.TCP提 ...

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

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

  5. [na]TCP的三次握手四次挥手/SYN泛洪

    1.TCP报文格式 上图中有几个字段需要重点介绍下: (1)序号:Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记. (2)确认序号:Ack序号,占32位, ...

  6. 救救孩子吧,到现在还搞不懂TCP的三次握手四次挥手

    本文在个人技术博客同步发布,详情可用力戳 亦可扫描屏幕右侧二维码关注个人公众号,公众号内有个人联系方式,等你来撩...   前几天发了一个朋友圈,发现暗恋已久的女生给我点了个赞,于是我当晚辗转反侧.彻 ...

  7. TCP/IP三次握手四次挥手

    本文通过图来梳理TCP-IP协议相关知识.TCP通信过程包括三个步骤:建立TCP连接通道,传输数据,断开TCP连接通道.如图所示,给出了TCP通信过程的示意图. TCP 三次握手四次挥手 主要包括三部 ...

  8. TCP协议—三次握手四次挥手的原理<转>

    三次握手四次挥手的原理   TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接.在TCP/IP协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的.三 ...

  9. 第6章 传输层(详解TCP的三次握手与四次挥手)

    第6章 传输层 传输层简介 传输层为网络应用程序提供了一个接口,并且能够对网络传输提供了可选的错误检测.流量控制和验证功能.TCP/IP传输层包含很多有用的协议,能够提供数据在网络传输所需的必要寻址信 ...

  10. 通俗了解TCP/IP三次握手四次挥手

    前言: tcp/ip通信机制是计算机中很重要的一个知识点,不是一句两句就能解释清楚的,需要反复推敲其中的玄妙. 通俗理解: 但是为什么一定要进行三次握手来保证连接是双工的呢,一次不行么?两次不行么?我 ...

随机推荐

  1. android studio gradle的坑

    国产模拟器别国外的好用.非常傻瓜.有人推荐夜神. 之前用geom,下载Android都得半天.     每次做开发前,配置环境都要搞半天.尤其是想快速学习一个技术的话,光装环境都让人放弃了.最近想看一 ...

  2. Asp.net Core依赖注入(Autofac替换IOC容器)

    ASP.NET Core ASP.NET Core (previously ASP.NET 5) 改变了以前依赖注入框架集成进ASP.NET的方法. 以前, 每个功能 - MVC, Web API, ...

  3. 【Spring】原来SpringBoot是这样玩的

    菜瓜:我自己去调Mvc的源码差点没给Spring的逻辑秀死...难受 水稻:那今天咱们看一个简单易用的SpringBoot吧 菜瓜:可以,这个我熟悉 水稻:熟悉? 菜瓜:当我没说,请开始你的表演 水稻 ...

  4. Spring笔记(3) - debug源码AOP原理解析

    案例 @EnableAspectJAutoProxy//开启基于注解的aop模式 @Configuration public class AOPConfig { //业务逻辑类加入容器中 @Bean ...

  5. tomcat发布时候jar包问题

    今天遇到个问题就是,启动tomcat时,报:java.lang.NullPointerException at org.apache.jsp.**_jsp.jspInit(index_jsp.java ...

  6. Netty源码学习系列之5-NioEventLoop的run方法

    前言     NioEventLoop的run方法,是netty中最核心的方法,没有之一.在该方法中,完成了对已注册的channel上来自底层操作系统的socket事件的处理(在服务端时事件包括客户端 ...

  7. 洛谷P2602 [ZJOI2010]数字计数 题解

    题目描述 输入格式 输出格式 输入输出样例 输入样例 1 99 输出样例 9 20 20 20 20 20 20 20 20 20 说明/提示 数据规模与约定 分析 很裸的一道数位DP的板子 定义f[ ...

  8. 【js】栈方法和队列方法

    栈方法:后进先出,推入(push)和弹出(pop):push("**")返回数组长度,pop()返回弹出的项. var colors = new Array(); // 创建一个数 ...

  9. 微信小程序中的深拷贝与浅拷贝问题

    最近在弄小程序项目的时候遇到了一个json对象复制的问题,也就是俗称的深拷贝与浅拷贝了. 一般用变量直接接收就是浅拷贝,那么如何理解浅拷贝与深拷贝的意义呢? 浅拷贝:只是将对象地址的复制,并没有开辟新 ...

  10. 【XCTF】ics-04

    信息: 题目来源:XCTF 4th-CyberEarth 标签:PHP.SQL注入 题目描述:工控云管理系统新添加的登录和注册页面存在漏洞,请找出flag 解题过程 进入注册页面,尝试注册: 进行登录 ...