【Linux】网络编程 —— 传输层协议 TCP(下)

🌈欢迎来到Linux专栏 ~~ 网络编程

网络编程

假设对方的接受能力是4000字节的话,那么我发送的时候,为什么直接一次发送4000字节呢?反而是发送了多个报文??

  • 答案在Mac帧处再讲解,主要原因是在数据链路层发送的数据不能太大,有长度限制

⚙️拥塞控制

之前我们了解到的策略都只是和发送端和接收端有关的! 但是这个报文会经过网络的,那不是就要考虑网络中的情况吗??

TCP为了保证可靠性,它不仅仅考虑了发送端和接收端的策略,还考虑了网络情况

一旦我们在通信时,出现了大规模的丢包问题,就判定是网络出现问题了 ------ 出现了网络拥塞

  • 丢一个两个报文,我们就进行重传!没问题✅️
  • 那么如果是500个报文,丢了495个,还需要进行重传吗?? ❌️不能立即进行重传!因为会加重网络的拥堵情况

像上图,如果出现了网络拥堵,还对丢包的报文大面积进行重传 ------ 网络里继续涌入大量的重传报文 ------ 加重网络拥堵

  • 不应该是大家都暂停一会,让我把拥堵情况先消化一下,再进行重传

🏝️拥塞控制

再进行下面改进时的前提是:网络已经拥塞了

TCP引入慢启动机制,先发少量的数据探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据

  • 发送一个,收到后;再发送两个也收到后、才发送四个...

此处引入一个新概念:拥塞窗口TCP 发送方根据网络拥塞状况动态控制的一个窗口大小,用来限制发送方在收到 ACK 之前最多可以向网络中发送多少数据

  • 发送数据超过该窗口,可能会发送网络拥堵 ------ 衡量网络拥塞的指标(网络的接收能力)

到现在我们认识了三个窗口

  1. win窗口 (报头窗口大小字段)
  2. 滑动窗口
  3. 拥塞窗口

这三个窗口的关系是什么呢??

滑动窗口大小 = minwin窗口 ,拥塞窗口)

  • win窗口防止"把接收方撑爆",拥塞窗口防止"把网络撑爆",TCP 实际能够发送的数据量取两者的较小值

1️⃣是怎么做到发送方一旦识别到网络拥塞,就可以灵活的控制它发送报文的数目呢?

  • 本质是通过拥塞窗口来限制滑动窗口大小
  • 拥塞窗口设置为1000,即便你接收能力再大,滑动窗口也只是1000;不断的增加拥塞窗口即可

但是真实情况下,拥塞窗口是不可能一直指数的增长的!因为要考虑对端的接受能力!

那怎么理解慢启动呢

  • 前期增长比较慢,1 - 2 - 4 -.... ,后期恢复特别快
  • 为了不增长的那么快,因此不能使拥塞窗口单纯的加倍。
  • 此处引入一个叫做慢启动的阈值
  • 当拥塞窗口超过这个阈值的时候,不再按照指数方式增长,而是按照线性式增长

当TCP开始启动的时候,慢启动阈值等于窗口最大值

在每次超时重发的时候,慢启动阈值会变成原来的⼀半,同时拥塞窗口置回1

少量的丢包(丢包率1% ~ 1.5%),我们仅仅是触发超时重传;大量的丢包(3%以上),我们就认为网络拥塞;

当TCP通信开始后,网络吞吐量会逐渐上升;随着网络发生拥堵,吞吐量会立刻下降

拥塞控制,归根结底是TCP协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案.

TCP拥塞控制这样的过程,就好像热恋的感觉

拥塞窗口大小一定是变化的!因为网络是变化的! 发送拥堵的上限一定是变化的

细节:那TCP自己是怎么知道,这个拥塞窗口大小一个是多少呢?

  • TCP也不知道,只能通过不断的试才知道
  • 慢启动 的本质:探索当前网络的接收能力!

🐴延迟应答

如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小

延迟应答的本质:通过延时,一定概率可以给发送方通告一个更大的接收窗口

⼀定要记得,窗口越大。网络吞吐量就越大,传输效率就越高。我们的目标是在保证网络不拥塞的情况下尽量提高传输效率

  • 那么如果拥塞窗口比较小呢?不一样发不了很多数据 ------ 和我没关系了啊,我已经尽量给到一个大的接收窗口了,网络拥塞是网络的事情了

那么所有的包都可以延迟应答么?肯定也不是

  • 数量限制 :每隔N个包就应答⼀次;
  • 时间限制:超过最大延迟时间就应答⼀次;

具体的数量和超时时间,依操作系统不同也有差异;在Linux里⼀般N2超时时间取200ms

♻️捎带应答

在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是"⼀发⼀收"的。意味着客户端给服务器说了"Howareyou",服务器也会给客户端回⼀个"Fine,thankyou"

那么这个时候ACK就可以搭顺风车,和服务器回应的"Fine,thankyou"⼀起回给客户端

  • TCP地位是对等的,我可以给你发,你也可以给我发

既然我要给你做应答 + 发数据,为什么不整合在一起呢?于是有了捎带应答:序号是自己的,确认序号是对收到数据 + 1

三次握手里的第三次的ACK可以带数据吗??

  • 对于发送方,第三次ACK是可以带数据的,因为ack发出发送方就认为三次握手就完成了
  • 如果这个ack没丢,那么接收方就可以拿到对应发送方发来的数据了 ------ 也叫 捎带应答

🆚TCP小节

为什么TCP这么复杂?因为要保证可靠性 ,同时又尽可能的提高性能

可靠性:

  • 校验和 ------ 校验失败,报文丢弃 再进行重传
  • 序列号(按序到达、去重)
  • 确认应答 ------ 对历史报文是100%可靠的
  • 超时重发、快重传
  • 连接管理 ------ 三次握手、四次挥手
  • 流量控制(滑动窗口)
  • 拥塞控制

提高性能:

  • 滑动窗口 ------ 让多个 TCP 数据段可以同时发送
  • 快速重传
  • 延迟应答
  • 捎带应答

✅️常考面试题

🌊面向字节流

创建⼀个TCP的socket,同时在内核中创建⼀个发送缓冲区 和⼀个接收缓冲区

  • 调用write时,数据会先写入发送缓冲区中
  • 如果发送的字节数太长,会被拆分成多个TCP的数据包发出
  • 如果发送的字节数太短,就会先在缓冲区里等待,等到缓冲区长度差不多了,或者其他合适的时间发送出去
  • 接收数据的时候,数据也是从网卡驱动程序到达内核的接收缓冲区
  • 然后应⽤程序可以调⽤read从接收缓冲区拿数据
  • 另⼀方面,TCP的⼀个连接,既有发送缓冲区,也有接收缓冲区,那么对于这⼀个连接,既可以读数据,也可以写数据。这个概念叫做全双工**

由于缓冲区的存在,TCP程序的读和写不需要一一匹配,例如:

  • 写100个字节数据时,可以调用一次write写100个字节,也可以调用100次write,每次写⼀个字节
  • 读100个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以⼀次read100个字节,也可以⼀次read⼀个字节,重复100次;

TCP 不关心你发送的是"一条消息"还是"一个文件",它只把数据看成一串连续的字节(byte),负责可靠、有序地把这串字节交给对方

🍔粘包问题

因为tcp是面向字节流的,所以会存在粘包问题!

那么如何避免粘包问题呢?归根结底就是⼀句话,明确两个包之间的边界

❌️TCP异常情况

进程终止 :进程终止会释放文件描述符,仍然可以发送FIN和正常关闭没有什么区别

机器重启 :和进程终止的情况相同(重启不也是 要对进程关闭嘛

机器掉电/网线断开 :网线被拔了后(发送端想告诉对方都不行了)即使没有写入操作,TCP自己也内置了⼀个保活定时器,会定期询问对方是否还在。如果对方不在,也会把连接释放

  • 接收端本地 socket 状态还认为连接 ESTABLISHED(连接存活),但对端早就已经断开连接了;当本机调用 write 往这个 "假活着" 的连接发数据的时候,内核发现实际连接已经失效,直接发出 RST 复位报文,把连接强制销毁
  • 如果拔的是服务器的网线呢? ------ 客户端认为链接还在,就会向对方发送数据 ,服务器端却不记得了,我们之间没建立链接,怎么就给我直接发数据了,服务器就会给发送端发送一个应答(其中RST置为1)要求链接进行重置

另外,应用层 的某些协议,也有⼀些这样的保活检测机制 。例如HTTP长连接中,也会定期检测对方的状态。例如QQ,在QQ断线之后,也会定期尝试重新连接.

📢写在最后

接下来登场的是 网络层 IP

相关推荐
weixin_BYSJ19872 小时前
flask民族服饰饰品商城小程序---附源码37399
java·javascript·spring boot·python·小程序·django·php
Light Gao2 小时前
企业级灰度发布技术方案
网络·数据库·oracle
Little Tian3 小时前
基于FPGA的UDP回环实验(二)----ARP模块
网络·网络协议·udp
程序员AlbertTu3 小时前
第2章 上手 Linux:环境与文件操作
linux·运维·服务器
今儿敲了吗3 小时前
CN——数据链路层(下)
网络·笔记
你怎么知道我是队长3 小时前
计算机网络入门指南:从OSI模型到网络设备
网络·计算机网络
K成长日志3 小时前
BLE链路层--比特流处理
网络·物联网·网络协议·蓝牙·iot·ble·无线
怪奇云呼军3 小时前
闪电智能VoiceAgent 如何管理呼入、接听、桥接和挂断状态?
java·前端·网络·数据库·人工智能
☆凡尘清心☆3 小时前
CentOS Stream 9 源码编译搭建 Zabbix7.0.29 完整部署方案(部署成功)
linux·运维·centos