数通面试 : TCP/UDP

数通面试第三篇 ~

今天来聊聊传输层的东西 , 其实对我们网工来说无异于 TCP / UDP 2种协议以及端口号的相关内容 

对于不太靠谱的三层IP(尽力而为模型)来说 , TCP 完成了很多 IP协议无法完成的事情

先来简单的问题当个开胃菜

 为什么需要TCP ? 

IP 层是「不可靠」的,它不保证网络包的交付、不保证网络包的按序交付、也不保证网络包中的数据的完整性。TCP 是一个工作在传输层可靠数据传输的服务,它能确保接收端接收的网络包是无损坏、无间隔、非冗余和按序的。

对于往上封装过程中  IP中的协议字段 6 /17 决定了4层是TCP(6)还是UDP(17)

 

 TCP和UDP有什么区别

这个问题相对来说还是比较简单的

TCP是面向链接的  --> 我们可以理解为打电话   我们直接有一个会话的关系  ,

  1. TCP是一个1对1的情况 ,  同时在开始传输数据之前一定需要进行三次握手
  2. TCP很可靠  你可以及时和我沟通(确认机制 / 重传机制 / 拥塞控制)  ,  没有数据丢失
  3. TCP的头部较为复杂 因为需要实现各种复杂的功能 你可以继续理解打电话  通知100个人 就会很麻烦
  4. 分片处理 , TCP协议中的数据包大小超过最大报文段长度(MSS),TCP在传输层进行分片。

 

我们再来看看UDP

UDP 是无连接的  --> 相较于打电话  这里我们可以理解为  对讲机 (电视剧里见过吧? 保安掏出来就是喊)

 

  1. UDP是一个1对多的情况  ,  当然也支持1对1  多对多 总之没有限制   开始传输数据之前也不需要建立链接
  2. UDP不可靠 , 当然也不是他的问题 UDP会尽量的去完成 (可以类比IP)
  3. UDP的头部比较简单 就是 源目端口号 + 包长度(注意TCP的是首部长度)  + 校验和
  4. 分片处理 , UDP协议包 如果超过了MTU  则会交给ip协议去分片 (他太简单了)

 为什么UDP头部是包长度 , 而TCP头部是首部长度?

UDP的包长度:

UDP头部的"包长度"字段指的是整个UDP用户数据报的长度,这包括了UDP头部和UDP数据载荷。由于UDP是一种简单的面向数据报的协议,它不将数据切分成多个部分进行发送;每个UDP数据报都是独立的,并且包含了全部的传输信息。因此,"包长度"字段是必要的,它告诉接收端这个数据报总共有多长,以便正确地从IP数据包中提取UDP数据报。

TCP的首部长度:

TCP头部的"首部长度"(也称为"数据偏移")字段是指TCP头部的长度,不包括TCP数据载荷。由于TCP是一种流式协议,它可以将数据切分成多个部分进行发送,而且每个部分可能会有不同的选项和大小的头部。TCP的"首部长度"字段告诉接收端在这个TCP段中头部有多长,这样接收端就知道从哪里开始读取实际的数据。这个字段是变长的,因为TCP头部可以包含多种不同的选项,如最大报文段大小(MSS)、窗口缩放因子、选择性确认(SACK)选项等。 TCP 有可变长的「选项」字段

 

 TCP和UDP的 应用场景

TCP :

  • FTP --> 需要保证文件数据的完整性和正确性
  • http/https --> 浏览网页,依赖TCP提供的可靠性和顺序保证。
  • SMTP(电子邮件) / SSH --> 依赖TCP来保证邮件内容不丢失、不损坏 以及可靠连接。

UDP :

  • VoIP -->(语音通信)或实时视频会议,UDP因为其低延迟特性而被选
  • DNS / SNMP:域名系统(DNS)查询通常使用UDP 也有小部分TCP,因为它们需要快速得到响应,且数据包通常很小。
  • 广播或多播应用:UDP适用于发送广播或多播消息,如某些类型的视频广播。

 重点关注一下TCP 

先来看看  TCP协议的报文 , 里面具体有哪些东西

重点关注一下 Seq 和Ack 值的理解 , 以及他们对应的Flags置位 ,

Sequence 序列号  

 报文循序的排列  对端可以检测丢失 请求重传
 这个是记录本端的 (会话2端各自维护了一个初始Seq  a / b)

 如这次Seq = a  , TCP载荷 x个字节

 本端下次发送就是a+x

 (x是上次发送内容的字节数 也就是对端 回复的ACK)

 在三次握手的情况下 没有数据 x就是假设有1个字节

Ack           确认号

 本端确认号= 接收到的对端Seq+x  (TCP载荷)

 (x: 我收到了你发送的x字节)

 1.我收到你seq为b的报文  

 2.告诉你可以发送b+x的报文了

Flags         标记

 (1字节 共8个flag)

 Flags的内容  , 其中6个是常用的 2个不常用

ACK , SYN , FIN需要重点学习一下

SYN=1(就是等于Flags 的SYN置位了)表示这是一个连接请求或连接接受请求。

在一个正常的TCP会话中 SYN只会被使用2次 -->三次握手中双方各自的第一次数据包中

在TCP所有的会话中 有且只有第一个包(通常是客户端发送的) , Flags只置位了SYN

其余所以的包中Flags都会多一个AKC 意思是 ACK只在>=2的包中出现

简单的理解一下 

第一个包Flags置位(SYN) 

第二个包FLags置位(SYN+ACK)

第三个包和后续所有的包Flags都不会出现SYN 但必定都有ACK

这样就多一个面试场景 比如说一条防火墙命令 设置了一个ACL  规则是只允许ACK置位的包通过

这是什么意思呢 ?

其实不难  ACK不在一个包出现  这样子设置 如果墙外服务主动访问墙内(第一个包没有ACK)

此时就会被这条规则拒绝  ,  只有里面发起才可以建立会话 防火墙才允许  --> 是不是很像DMZ区域的设计?

 

 

  TCP三次握手的过程  

先从Flags置位的角度来看 (上面已经详细阐述过了)

SYN

 

 

SYN+ACK

ACK

 

 

再从Seq序列号和ack确认值(注意值和flags置位的区分)的角度看

会话的双方各自维护了一个序列号  , 个人认为这个理解是很重要的  什么叫做各自维护?

 

Seq  : A  

ACK : 没有ACK

 

 

Seq : B 

ACK = A+1

 (ACK的A就是对端Seq的值 , 加对端TCP载荷的值 , 但是三次握手没有具体数据 , 所以为1 )

Seq : A+1  (seq = 本端上次Seq+ 本端上次数据载荷)

ACK : B+1 (对端Seq的值+ 对端TCP载荷)

 

 

简单理解一下 Seq是自己和自己算(+=载荷)的 因为三次握手是没有载荷数据的 默认为1 所以看起来会混淆

(双方的TCP载荷可能是不一样的 , 比如我这边只做确认没有发送数据 本端Seq增值就很慢)

ACK是确认收到对方的seq 以及 对方的载荷  , 2个值加起来就是ACK了

 

 为什么链接是三次断开是四次  

三次链接:

比如说我们来模拟建立会话 2次的情况下

A : 你好 , 我需要建立链接(Seq)

                                   你好 , 我需要建立链接(Seq)  , 我准备好了(ACK) : B

这样是不是感觉很奇怪 B服务端是没办法得知 客户端A有没有准备好

因为只有收到了A的ACK  B才能确认A收到了B发送的确认

 

虽然从理论上说,两次握手也能建立起一个连接,但实际上,这会大大降低连接的可靠性和稳定性

这也会导致另外一个问题 :

如果一个失效的连接请求(例如,由于网络延迟而晚到的旧SYN报文)到达服务器,两次握手会使得服务器错误地认为这是一个新的连接请求,并建立连接。这可能导致服务器资源的浪费,并可能打开一条不再需要或不再期望的连接。

 

四次挥手:

老样子 我们来模拟一下 断开会话   断开么 我直接走人不行么?

A : 你好 , 再见~          

                                    …………. : B

是不是看上去没啥问题?  但如果B还有话说呢 ?

首先明确一个观点 

这个会话关闭是基于双方的 

我发如果信息发送完毕 但是对方还有信息还需要发送呢?

我结束 发送FIN置位  --> 对端发送ACK确认知晓我要离开

对端结束 发送FIN置位  <-- 我发送ACK确认知晓对端要离开

至此 TCP连接断开 

但是实际环境中 并不总会抓到4次完整挥手 , 这是另外一个情况了 , 基于设计 可能没有第四个ACK , 也可能等半天没反应就释放资源断开会话了 都存在

 

 TCP累加确认机制

当然实际环境中不可能是一句一确认的

 (想想一下你和你领导打电话 你领导说一句你附和一句 "好 , 知道 "   这也太舔狗了 领导也嫌你烦)

实际场景是多个TCP后 , 回复一下 (seq+多个包总载荷)  , 这就是累加确认 , 比如我连续发3个载荷为1000的包

然后你确认了ack为 Seq = a+4000

累加确认 

连续3个载荷 x =1000 

Seq = a+(1000)  -->

Seq = a+(2000)  --> (是不是很难理解连续三个载荷1000 不是3个a+1000? , 回想一下序列号的作用)

Seq = a+(3000)  -->

                                          <--   Seq = a+(4000)

实际应该是5-7个包回复一次 , 如果 回复的ACK值不等于a+4000 ,  这说明有TCP需要重传了

因为收到的载荷数量对不上 ,  此时的重传机制就是到之前你的回复节点起 开始重传

(有比较牛x的技术可以精确具体到重传你丢失的某个包 或者从丢失点开始重传 , 这里不做展开讨论)

 

 

 TCP的滑动窗口机制

window字段 , 之前不是讨论了累加确认的机制么  ,  有没有想过这么一个问题

如果我这边很忙 , 但是对端还是源源不断的快速发送一些数据来让我处理  ,  这样子就容易造成拥塞 所以

滑动窗口机制帮助进行流量控制,确保发送方不会因发送过多数据而淹没接收方或网络。

果接收方的窗口大小变为零(即没有可用的缓冲区),它会通知发送方停止发送数据。当接收方准备好接收更多数据时,它会更新窗口大小并通知发送方。

 

 

RTT 超时时间动态调整技术

重传的可能性可以分为三种  :

去的时候丢了 

回的时候丢了

超时 --> 我们来重点讨论一下超时

字面理解类似ICMP , 我等待一段时间没有收到你的回复你的ACK 我不知道你是丢了还是正在路上 , 但是我也不可能无限制的等待下去 ,  这里你可以说 那不简单 , 设置一个常见的数值不就行了 , 比如大于多少微妙就算超时 .

那么你访问外国的节点的呢? 跨越几千公里的场景下延迟必然高 , 你不能说你来得慢我就不等你了 人家还在路上呢

所以这个超时时间如何设置是大有学问的  , 这里就引出我们的主角 RTT (Round-Trip Time)

TCP(传输控制协议)中的超时时间动态调整技术主要是基于往返时间(Round-Trip Time, RTT)的测量。RTT是指一个数据包从发送方发送到接收方,并且接收方发送确认(ACK)返回给发送方所需的总时间。动态调整超时时间是TCP可靠性和效率的关键因素之一。

网工不比拘泥这些细节的实现 , 了解即可

SRTT = SRTT + α (RTT – SRTT) :计算平滑RTT;

DevRTT = (1-β)*DevRTT + β*(|RTT-SRTT|) :计算平滑RTT和真实的差距(加权移动平均);

RTO= μ * SRTT + ∂ *DevRTT : 加权平均公式。

 

 

结尾照例放出一些面试题 仅供参考

  • TCP 与 UDP 的区别是什么?请举例说明在什么场景下会选择使用它们。
    这个问题考察应聘者对两个主要传输层协议的理解和实际应用能力。
  • 描述 TCP 的三次握手和四次挥手过程。为什么是三次握手而不是两次或四次?
    这一问题旨在检验应聘者对 TCP 连接建立和终止过程的深入理解。
  • 什么是 TCP 拥塞控制?请解释 TCP 的拥塞控制算法,例如慢启动、拥塞避免、快重传和快恢复。
    此题目考查应聘者对 TCP 性能优化和网络流量管理的知识。
  • 在 TCP 连接中,发生丢包时会怎样?TCP 如何检测和恢复丢失的数据包?
    这个问题测试对 TCP 的可靠性机制的理解。
  • 解释什么是 TCP 窗口缩放和选择确认(SACK)。它们是如何改进 TCP 性能的?
    这一问题探讨 TCP 协议的高级特性及其对数据传输性能的影响。
  • 描述一个你遇到的关于传输层的复杂问题,以及你是如何解决的。
    这个问题旨在了解应聘者的实际工作经验,特别是在问题解决和故障排除方面的能力。
  • 在面对网络拥堵时,UDP 和 TCP 分别如何表现?在这种情况下,如何优化 TCP 传输性能?
    这个问题考察应聘者对网络状况变化时协议表现的理解,以及对性能调优的能力。
  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孤单77

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值