拒绝八股!通俗易懂带你理解TCP协议,轻松拿捏面试官!

一口Linux 2023-11-20 11:50
点击左上方蓝色“一口Linux”,选择“设为星标


第一时间看干货文章 

【干货】嵌入式驱动工程师学习路线
【干货】一个可以写到简历的基于Linux物联网综合项目
【干货】Linux嵌入式知识点-思维导图-免费获取



 1

前言

我本人是比较抗拒背八股的,我主张去理解知识,让它真的成为你的一部分,这样在表达的时候就会非常流利,我常和我朋友说每次我面试的时候对于这些八股都是在简单的吟诵,因为我真的理解掌握了这些知识。但是网络、计算机组成的具体内容确实不像代码一样容易理解,所以很多人只能死记硬背。

其实这些所谓的八股,除了设计者和专精的工程师,又有多少人能真正确定自己对这些知识的理解是没有错误的呢?只要在面试中表达出自己的理解,而不是死记硬背,相信就能够和普通的候选人拉开差距了。

闲话少说,下面是我对于TCP协议的一些个人理解,可能会带有错误,欢迎大家指正。

不简单的TCP协议

TCP内部的实现是很复杂的,我会从流量控制、可靠交付、拥塞控制、TCP报文、三次握手四次挥手、重传时间等内容和大家稍微聊聊TCP的具体实现,以及为什么要这么做。

TCP的地位:是整个网络协议族中最重要的一个,TCP在网络协议族中是很特别的,因为整个网络,我们姑且分为课本上的五层吧,从下到上即物理层、数据链路层、网络层、传输层、应用层五层,只有传输层的TCP能做到可靠交付,这也是为什么很多应用都是用TCP的原因,所以在面试中TCP绝对是重点中的重点。

TCP:传输控制协议(英语:Transmission Control Protocol,缩写:TCP)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。在简化的计算机网络OSI模型中,它完成第四层传输层所指定的功能。用户数据报协议(UDP)是同一层内另一个重要的传输协议。

在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。

应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分割成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来透过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认信息(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失并进行重传。TCP用一个校验和函数来检验数据是否有错误,在发送和接收时都要计算校验和。(维基百科)

TCP报文


1.源端口,目的端口:每个两字节

2.序号:两字节,TCP的每个字节都按照序号编序(这也是面向字节流的一个标志),建立连接时序号是随机的 而后的序号都在此基础上递增。比如我第一次握手seq=10086 第三次握手seq=10087 之后又传了一百字节的数据,那么再发数据,seq=10087+100+1=10188。

3.确认号:两字节,希望对方下一个报文段的序号 这也是为什么握手的时候ack=seq+1 确认号代表前面序号的字节都已经成功按序收到(捎带确认机制),当客户端发送过来的序号seq=10086时,报文长度为200,那么服务端的ack应该是12087,表示对之前所有报文的确认。

4.数据偏移:四位,实际上表示的是首部长度,最大十进制数转换过来对应的是15,代表头部最多大小为60字节,所以TCP头部的长度应该是20-60间以4字节为单位变化的,不可能出现30字节长度的TCP头部

5.保留:六位,今后使用

然后就是6个控制位,每个1为,数据偏移+保留+6控制位=2字节

6.紧急URG:表明该报文优先级很高,当URG=1时,报文会被放在发送方此次发送报文的最前端进行优先发送

7.确认ACK:ACK=1 确认号有效 建立连接之后 每次ACK=1

8.推送PUSH:PUSH=1 立即创建一个报文段发送出去(用得少)

9.复位RST:RST=1 表示TCP连接出现严重错误,需要重新连接

10.同步SYN:SYN=1 表明这是一个连接请求报文

11.窗口:2字节,滑动窗口的大小 我们后面细说

12.检验和:2字节,这个用途和UDP的一样,加上12字段伪首部之后进行校验

13.紧急指针:2字节,只有当URG=1时才有意义,指出本报文段中紧急数据的字节数

14.选项:长度可变,最大40字节(窗口扩大选项、时间戳选项等等)

TCP的特点

  • 连接点对点

  • 全双工 A可以给B发 B也可以给A发

  • 面向连接 只有连接建立完成 才可以发数据

  • 拥塞控制 主要是通过以下机制来完成的(慢开始 拥塞避免 快恢复和快重传)

  • 可靠交付

  • 面向字节流

这些下面都会一一介绍

TCP和UDP的区别

TCP是一个复杂的协议 而UDP比较简单

1.连接 TCP是一个面向连接的协议 而UDP是一个无连接协议 即TCP需要连接建立之后才能传输数据 而UDP在未建立连接时就能够传输数据

2.交付 TCP是一个可靠交付的协议 而UDP只能尽最大努力交付 可靠交付指的是数据按序到达 不丢失 不重复

3.数量 TCP是一个点对点的全双工协议 而UDP支持一对一 一对多 多对多

4.首部长度 TCP的首部长度更长 20-60字节 而UDP的首部固定为8个字节

5.面向 TCP面向的是字节流 即上层应用层交付下来的数据报 在TCP的眼中是一串字节流 而UDP是面向数据报的

6.是否具有拥塞控制 TCP是有拥塞控制的 在网络拥塞时源点主机的发送速率会降低 而UDP不具有拥塞控制 一些追求传输效率的应用通常使用UDP协议

所谓面向字节流 指的是TCP发送端发送几次数据和接收端接受几次数据时没有必然联系的

比如发送端调用一次write写了一百个字节 但是接受端可以分10次接受 也可以写10次100字节 接收端一次接收完

原因:

TCP面向连接 一个Socket收到的数据由同一台数据发出 并且有序到达 所以每次读取多少数据都可以 因为我知道前面的数据都是对的 某些时候为了节省资源 程序可能会选择"攒一会"再读

而UDP协议不知道前面的数据是否是错的 所以每次发送就对应着一次接收 如果错了就再发

应用区别:

UDP:追求高速度的应用一般用的是UDP(KCP),比如视频、音频、实时游戏、广播,而且通常这些应用对于数据的可靠性要求不是很高,视频丢点数据(丢几帧 后面再补上),你也看不出来,但是速度慢就不能接受了,玩英雄联盟慢一秒别人就把你头打爆了

TCP:可靠传输,HTTP用的就是TCP(后面用为了追求性能用UDP去了,我们之后详说),任何确保数据可靠的应用都应该使用TCP

典中典之三次握手 四次挥手

相信很多同学都听说过三次握手 四次挥手的问题,也大概知道过程是什么样的,但是自己讲很难讲清楚,我们现在来捋一捋这到底是是个什么过程,以及为什么要三次握手四次挥手

注:下文的客户端和服务器是站在应用层角度的,可以理解成发送方和接收方

三次握手


第一次握手:客户端向服务器发送TCP请求连接报文,SYN置1,seq=x (都知道SYN和seq是啥吧)

第二次握手:服务器收到报文,发送TCP确认报文,SYN=ACK=1,seq=y ack=x+1

第三次握手:客户端收到报文,发送ACK=1,seq=x+1,ack=y+1

怎么记忆这个过程呢?

第一次和第二次握手 都属于正儿八经连接建立的过程 我们之前说过SYN置一的情况是请求连接报文才有的 所以前两次握手是有SYN的

第三次握手是对前两次握手的确认过程 即确认 客户端感知到服务器的存在 服务器也知道客户端的存在 所以不需要SYN

因为第一次握手发送的报文是没有实体数据的,所以第三次握手seq=第一次握手seq+1

注:第三次握手可以带数据 前面两次不行

为什么需要三次握手

这个一般是和三次握手一起问的

我个人理解有两个原因

1.TCP是面向连接的 如果只进行两次握手 服务器其实是不知道连接是否建立成功的

2.如果只进行两次握手,那么会出现这么一种情况,因为网络延迟,客户端向服务器发了一次连接请求报文,但是服务器暂时没收到,然后客户端又发了一次,这次服务器收到了,两次握手成功了,这时第一次发送的请求来了,服务器也会做出响应,就会同时有两个TCP连接,浪费资源。但是如果有三次握手的话,服务器进行确认的时候,客户端会忽略掉这次确认(想一想为什么)

四次挥手


第一次:客户端主动发送断开请求,FIN=1(这是一个请求断开的报文),seq=x

第二次:服务器收到之后 发送 ACK=1 seq=v ack=x+1 然后处于半关闭状态Close-wait

第三次:服务器发送FIN=1 ACK=1 seq=w ack=x+1

第四次:客户端收到后 发送ACK=1 seq=u+1 ack=w+1

一些解释

1.第三次为什么seq=w 是因为我们假设第二次到第三次的期间 服务器还在发数据

2,为什么第三次也有ACK字段

个人理解:TCP报文规定了只要建立连接之后所有报文都有ACK字段,所以其实第一次也有ACK字段的,只是大部分教材没有画出来

(八股文的很多细节是无法深究的 不是TCP的设计者谁知道真相是什么呢 我觉得只要有自己的理解 就已经超越很多死背书的人了)

3.为什么服务器连着给客户端发两次 一次不行吗?

第一次是对客户端发来的确认

第二次是请求和客户端断开

而且在这两次发送报文之间 服务器是可以发送数据的 客户端不行

为什么需要四次挥手

服务器决定进行第二次挥手和第三次挥手,某些时候把两次挥手合并,因为中间等不等待其实是由服务端应用程序决定的(handler),如果没有数据要发,同时又开启了tcp的延迟确认,那么就会合并挥手,这也是抓包的时候为什么能抓到三次挥手的包。

为什么需要等待2MSL

1.释放的端口可能会重连刚断开的服务器端口,而第二次挥手之后服务器还在给该端口发数据,如果不等的话,在这个通道里的老TCP报文可能和新的报文冲突,造成数据紊乱,2MSL(两倍生存时间,原因我推测可能是计算客户端发送给服务器,服务器处理之后再返回过来)是足够让客户端全部收到第二次挥手后的数据的。具体的时间不同版本其实也不一样,有兴趣的同学可以深入了解

2.保证确认断开,如果最后一次确认丢失了,服务器会重新进行第三次挥手,这样客户端还能够对第三次挥手的FIN报文进行处理

TCP怎么保证可靠交付

这个问题是一个很广泛的问题 基本把所有TCP的设计思想都包含了

什么是可靠交付?

我认为最起码要做到这几点:数据不丢 数据不重 数据按序 数据不错

1.数据不丢:TCP使用了确认-重传机制,对每一个收到的正确报文进行确认(ack),如果发现有数据没有被确认,就重传,其中重传又有超时重传和快重传

2.数据不重/不错:接收方会对数据进行检验。重复的数据丢弃,错误的数据丢弃,并不进行确认。

3.数据按序:流量控制,不至于一下发很多报文,而且会对数据包进行重新排序

TCP确认-重传机制

相信大家已经懂什么是确认了吧,简单来说,接收端发送ack=10001的报文,就说明从连接开始的序列号(假设是100)到ack-1(10000)的报文都是可靠交付的。

重传也很简单,我们先来聊聊超时重传

什么时候重传呢?

其实TCP在传递数据的时候,会设置一个超时计时器,当超时计时器触发了,发送端还没有收到来自接收端的确认报文,那么就认为这个消息没成功传递,原因可能有很多,网络阻塞,丢包,数据出错等等

问题来了:超时计时器怎么设置呢?每一个数据的超时时间都不一样吗?怎么能做到既不浪费算力,又能高效确认超时呢?

首先超时时间肯定不能选的很短,不然会很容易重发,浪费很多资源。

也不能很长,因为发送端只有收到确认之后才回删除数据,这样会浪费发送端的资源。

所以重传时间RTO我们一般设为比平常报文的平均往返时间稍微长一点点

具体公式如下:

RTTS(加群啊平均往返时间)=(1-a) x 旧的RTTS+ a x RTTS RFC文档推荐 a=0.125

RTTD(RTT偏差加权值) =(1-b) x 旧的RTTD + b x (RTTS-RTTD) RFC文档推荐b=0.25

RTO=RTTS+4 * RTTD

而每次触发超时重传 RTO=2 X RTO

TCP的流量控制

什么是流量控制?为什么要流量控制?

简单来说流量控制就是接收方通过参数控制发送方的速度,记得我们上文讲到的TCP报文的窗口字段吗,这个就是调控的因素,当接收方的缓存变少,就把窗口变小,发送方就会把数据发的慢一点,窗口的大小就是发送速度的大小

而我们提到的这种方案,就是TCP的滑动窗口,它的思想与算法中的滑动窗口类似,维护一个变长的窗口值,落在窗口里的就是可以发送的,在窗口后面的就是发完了的,窗口前面的就是还没发的,窗口是以字节为单位的,这也能体现TCP的面向字节流思想。

注意:发送端和接收端的窗口大小不可能做到完全同步,因为网络具有时延,当窗口为0的时候,发送端不再发送数据,待接收端缓冲区有空间了之后,会重新打开滑动窗口,让发送端继续发送数据。

TCP的拥塞控制

什么是拥塞?

拥塞:对网络中的某种资源的需求超过了资源可提供的部分

TCP采用四种算法避免拥塞

我们把A设为发送方 B设为接收方

发送方维护一个cwnd(拥塞窗口)的动态变量,其值取决于网络的拥塞程度,还有一个慢启动门限ssthresh状态变量

原则:没有拥塞,把cwnd变大,拥塞了,把cwnd缩小 思想很简单,实现很复杂

现在是不是有点蒙,之前不是提到了发送窗口大小吗,怎么又来了个拥塞窗口,A到底用什么速度发数据

经查证:发送窗口大小等于min(cwnd,B的接收窗口)

1.慢开始:cwnd小于ssthresh时,采用这种算法,cwnd大小按照指数扩容,每次 x 2

2.拥塞避免:cwnd>=ssthresh时,采用这种算法,cwnd按照常数扩容,每次+1

判断拥塞:当网络中有一段数据重传,则认为网络拥塞,ss变为拥塞时的一半,cwnd变为1

大家是不是觉得很不科学,因为丢包是很正常的,再牛逼的网络也会丢包,重传一次就认为拥塞,cwnd可能永远都等于1

因此TCP还有一种重传机制

3.快重传:不需要等到超时才进行重传,当B给A连着发了三次ack一致的确认报文,A就认为数据丢失了,重发ack之后的数据

4.快恢复:当快重传被触发时,同时执行快恢复算法,ss=拥塞时的一半,cwnd=ss,执行拥塞避免算法

TCP到底用的是超时重传还是快重传

相信如果你听懂了上面的内容,你脑子里应该有这个疑问

TCP到底是两种都用,还是拥塞的时候用快重传,平常使用超时重传呢?

我们计网老师说的是后者,但是TCP是如何判断网络是否拥塞的呢,已经建立连接的TCP能动态修改重传策略吗?

从业务的角度来说我觉得答案更可能是前者,毕竟这么玩能提高速度。

结语

今天的内容到这里就结束了,如果对您有所帮助,欢迎点赞、评论、收藏,您的支持就是对我最大的鼓励。

end



一口Linux 


关注,回复【1024】海量Linux资料赠送

精彩文章合集

文章推荐

【专辑】ARM
【专辑】粉丝问答
【专辑】所有原创
专辑linux入门
专辑计算机网络
专辑Linux驱动
【干货】嵌入式驱动工程师学习路线
【干货】Linux嵌入式所有知识点-思维导图

一口Linux 写点代码,写点人生!
评论
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 150浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 113浏览
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 140浏览
  • 故障现象 一辆2007款日产天籁车,搭载VQ23发动机(气缸编号如图1所示,点火顺序为1-2-3-4-5-6),累计行驶里程约为21万km。车主反映,该车起步加速时偶尔抖动,且行驶中加速无力。 图1 VQ23发动机的气缸编号 故障诊断接车后试车,发动机怠速运转平稳,但只要换挡起步,稍微踩下一点加速踏板,就能感觉到车身明显抖动。用故障检测仪检测,发动机控制模块(ECM)无故障代码存储,且无失火数据流。用虹科Pico汽车示波器测量气缸1点火信号(COP点火信号)和曲轴位置传感器信
    虹科Pico汽车示波器 2025-01-23 10:46 58浏览
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 143浏览
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 189浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 186浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 117浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 616浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 293浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 209浏览
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 418浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦