0
点赞
收藏
分享

微信扫一扫

模块化CSS

素的盐 2023-10-01 阅读 26

文章目录

大家好,我是晓星航。今天为大家带来的是 网络原理之TCP_IP 相关的讲解!😀

4.传输层重点协议

负责数据能够从发送端传输接收端。

4.1TCP协议

TCP,即Transmission Control Protocol,传输控制协议。人如其名,要对数据的传输进行一个详细的控制。

4.1.1TCP协议段格式

  • 源/目的端口号:表示数据是从哪个进程来,到哪个进程去;
  • 32位序号/32位确认号:后面详细讲;
  • 4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);首部长度的单位是4字节而不是字节。如果首部长度是15,那么TCP头部最大长度是 15 * 4 = 60 (长度是可变的) 后面的6位为保留位,可以类比于保留字。
  • 6位标志位:
    • URG:紧急指针是否有效
    • ACK:确认号是否有效
    • PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
    • RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段
    • SYN:请求建立连接;我们把携带SYN标识的称为同步报文段
    • FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段
  • 16位窗口大小:后面再说
  • 16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的检验和不光 包含TCP首部,也包含TCP数据部分。
  • 16位紧急指针:标识哪部分数据是紧急数据;
  • 40字节头部选项(option):此处的选项相当于对这个 TCP 报文的一些属性进行解释说明的(可有可无)。

4.1.2TCP原理

TCP对数据传输提供的管控机制,主要体现在两个方面:安全和效率。

这些机制和多线程的设计原则类似:保证数据传输安全的前提下,尽可能的提高传输效率。

4.1.2.1确认应答机制 ACK(安全机制)

A 给 B 发了个信息,B 收到之后就会返回一个 应答报文(ACK) — answer,此时 A 收到应答之后,就知道了刚才发的数据已经顺利到达 B 了。

[唐僧讲经例子]

TCP将每个字节的数据都进行了编号,按照字节来编号的。即为序列号。

每一个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发。(通过引入 序号确认序号 来区分当前应答报文是针对那个数据进行的了)

例如,主机A发送的当前数据序号是400,数据长度是100,则接收端收到后会返回一个确认号是501的确认号给主机A。

如果我们要找1 - 1000 的报头,此时1 - 1000 都是属于一个 TCP 数据包的,所以他的报头只需要填 1 就行了。

同理,1001 - 2000 的报头就是 1001。

2001 - 3000 的包头就是 2001。

TCP进行可靠性传输,最主要就是靠这个确认应答机制。

4.1.2.2超时重传机制(安全机制)

丢包可能是数据丢包

但是,主机A未收到B发来的确认应答,也可能是因为ACK丢失了;

因为我们数据丢包了,因此我们就会进行重新传输来应对这一丢包问题。

因此主机B会收到很多重复数据。那么TCP协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉。

这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果。

那么,如果超时的时间如何确定?

TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间。

4.1.2.3连接管理机制(安全机制)

在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接

三次握手:

SYN(synchronize):客户端主动给服务器发起的建立连接请求,称为"SYN",同步报文段。 这里的同步在我们图上理解就是创建连接的意思,只不过这里我们把他称作为同步。

ACK:应答报文。

上述粉框框住的地方是我们 TCP 的状态。

三次握手,建立连接阶段,主要认识两个状态:

  1. LISTEN 服务器状态。
    表示服务器已经准备就绪,随时可以有客户端来建立连接了。相当于 手机开机,信号良好,随时可以有人来打电话了
  2. ESTABLISHED 客户端和服务器都有
    连接建立完成,接下来就可以正常通信了。
    相当于电话拨打过去,对方接通了。

蓝框里面描述了 TCP 和 socket api 之间的关系。此处的 socket api 是系统原生api(C 语言版本的),这个和 Java 版本的已经有一定差距了。

所谓的三次握手,本质上是"四次"交互。 — 通信双方,各自要向对方发起一个 “建立连接的请求”。同时,再各自向对方回应一个 ack ,共四次。但是中间两次交互,是可以合并成一次交互的。因此就构成了"三次握手"。

那么问题来了,为什么要把中间两次合并?不合并行不行?

答:必须合并!!!因为这里涉及到封装分用,封装分用两次比封装分用一次成本更高。

三次握手另外一个重要的作用:验证同行双方各自的发送能力和接受能力是否正常。

三次握手的意义:

  1. 让通信双方各自建立对对方的"认同"
  2. 验证通信双方各自的发送能力和接收能力是否 ok。
  3. 在握手的过程中,双方来协商一些重要的参数

如果未来我们去面试,面试官问我们什么是三次握手过程,请你描述一下、

此时我们最好自带一套纸笔去面试,再描述三次握手的时候边画图边讲解!!!

向上述这样画图即可,中间一次过程合并了一次交互!

四次挥手:

四次挥手,关闭连接阶段,主要认识两个状态:

  1. CLOSE_WAIT 出现在被动发起断开连接的一方
    等待关闭。(等待调用 close 方法关闭 socket)
  2. TIME_WAIT 出现在主动发起断开连接的一方
    假设是客户端主动断开连接。当客户端进入 TIME_WSIT 状态时候,相当于四次挥手已经挥完。
    此时这里的 TIME_WAIT 要保持当前的 TCP 连接状态不要立即就释放。

注意,在断开连接的过程中,中间两次,通常情况下不能合并。(特殊情况下可以)—两个数据发送的时机相同,才能合并。如果是不同时机,就合并不了。

三次握手中间两次可以合并是因为他俩是同一时机。具体来说,三次握手这三次交互过程,是纯内核中完成的。(应用程序感知不到,也干预不了)
服务器的系统内核收到 syn 之后,就会立即发送 ack 也会立即发送 syn 。

而四次握手里面,FIN 的发起,不是由内核控制的,而是应用程序,调用 socket 的 close 方法 (或者进程退出),才会触发 FIN。
而ACK 则是由内核控制的,是收到 FIN 之后,立即返回 ACK。
因此四次握手中,中间两次过程不可直接合并,因为他们之间会有一个时间差,他们不是同一时机发出的。

如果未来我们去面试,面试官问我们什么是四次挥手过程,请你描述一下、

此时我们最好自带一套纸笔去面试,再描述四次挥手的时候边画图边讲解!!!

这里的 四次挥手 和上面的 三次握手 ,同样是存在超时重传的。

如果是最后一个ACK丢包了,站在服务器的视角来看,服务器是不知道是因为 ACK 丢了,还是自己发的 FIN 丢了,所以他会统一视为 FIN 丢了,统一进行重传操作。

既然服务器可能要重传 FIN,客户端就需要能针对这个重传的 FIN 进行 ACK 响应。很明显,如果刚才彻底把连接释放了,这样的 ACK 就无法进行了。因此使用 TIME_WAIT 状态保留一定时间,就是为了能够处理最后一个 ACK 丢包的情况,能够在收到重传的 FIN 之后,进行 ACK 响应。

服务端状态转化:

客户端状态转化:

下图是TCP状态转换的一个汇总:

关于 “半关闭” ,男女朋友分手例子

关于CLOSING状态。

TIME_WAIT

想一想,为什么是TIME_WAIT的时间是2MSL?

CLOSE_WAIT

一般而言,对于服务器上出现大量的 CLOSE_WAIT 状态,原因就是服务器没有正确的关闭 socket,导 致四次挥手没有正确完成。这是一个 BUG。只需要加上对应的 close 即可解决问题。

4.1.2.4滑动窗口(效率机制)

刚才我们讨论了确认应答策略,对每一个发送的数据段,都要给一个ACK确认应答。收到ACK后再发送 下一个数据段。这样做有一个比较大的缺点,就是性能较差。尤其是数据往返的时间较长的时候。

既然这样一发一收的方式性能较低,那么我们一次发送多条数据,就可以大大的提高性能(其实是将多 个段的等待时间重叠在一起了)。

那么如果出现了丢包,如何进行重传?这里分两种情况讨论。

情况一:数据包已经抵达,ACK被丢了。

这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认;

情况二:数据包就直接丢了。

这种机制被称为 “高速重发控制”(也叫 “快重传”)。

4.1.2.5流量控制(安全机制)- 接收方

接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。

因此TCP支持根据接收端的处理能力,来决定发送端的发送速度。这个机制就叫做流量控制(Flow Control)

接收端如何把窗口大小告诉发送端呢?回忆我们的TCP首部中,有一个16位窗口字段,就是存放了窗口 大小信息;

那么问题来了,16位数字最大表示65535,那么TCP窗口最大就是65535字节么?

实际上,TCP首部40字节选项中还包含了一个窗口扩大因子M,实际窗口大小是 窗口字段的值左移 M 位;
比如窗口大小已经是 16位 即64kb 它里面的扩展因子写了个 2,意思就是让
64KB << 2 = > 256KB

由于接收方缓冲区剩余空间是一直在动态变化的,所以每次返回 ack 带的窗口大小都在变化,发送方也是在动态调整。

4.1.2.6拥塞控制(安全机制)- 中间节点过程

虽然TCP有了滑动窗口这个大杀器,能够高效可靠的发送大量的数据。但是如果在刚开始阶段就发送大量的数据,仍然可能引发问题。

因为网络上有很多的计算机,可能当前的网络状态就已经比较拥堵。在不清楚当前网络状态下,贸然发 送大量的数据,是很有可能引起雪上加霜的。

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

像上面这样的拥塞窗口增长速度,是指数级别的。“慢启动” 只是指初使时慢,但是增长速度非常快。

  • 当TCP开始启动的时候,慢启动阈值等于窗口最大值;
  • 在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1;

少量的丢包,我们仅仅是触发超时重传;大量的丢包,我们就认为网络拥塞;

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

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

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

4.1.2.7延迟应答(效率机制)

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

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

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

具体的数量和超时时间,依操作系统不同也有差异;一般N取2,超时时间取200ms;

4.1.2.8捎带应答(效率机制)

在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 “一发一收” 的。意味着客户端给服务器说了 “How are you”,服务器也会给客户端回一个 “Fine, thank you”;

那么这个时候ACK就可以搭顺风车,和服务器回应的 “Fine,thank you” 一起回给客户端

本来是不同实际,在延时应答下,可能成为相同的时机,就合并了。
TCP 三次握手,本身就是相同时机。

三次握手是一定会合并的,此处有一定概率合并,这里和 四次挥手 的合并更像!

其他特性:面向字节流

其他特性:缓冲区

**其他特性:大小限制 **

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

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

4.1.3粘包问题

[八戒吃馒头例子]

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

思考:对于UDP协议来说,是否也存在 “粘包问题” 呢?

4.1.4TCP异常情况

进程终止:进程终止会释放文件描述符,仍然可以发送FIN。和正常关闭没有什么区别。 相当于 socket.close()

机器重启:和进程终止的情况相同。

机器掉电/网线断开:接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就会 进行reset。即使没有写入操作,TCP自己也内置了一个保活定时器,会定期询问对方是否还在。如果对方不在,也会把连接释放。

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

心跳包:就是在客户端和服务器间定时通知对方自己状态的一个自己定义的命令字,按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。

A发送一个心跳包,那么B也会回复一个心跳包,如果B没有回一个心跳包,那么就是B机器挂了。

4.1.5TCP小结

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

可靠性:

提高性能:

其他:

4.1.6基于TCP应用层协议

  • HTTP
  • HTTPS
  • SSH
  • Telnet
  • FTP
  • SMTP

当然,也包括你自己写TCP程序时自定义的应用层协议;

4.2UDP协议

4.2.1UDP协议端格式

4.2.2UDP的特点

UDP传输的过程类似于寄信。

无连接

知道对端的IP和端口号就直接进行传输,不需要建立连接;

不可靠

没有任何安全机制,发送端发送数据报以后,如果因为网络故障该段无法发到对方,UDP协议层也不会 给应用层返回任何错误信息;

面向数据报

应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并;

用UDP传输100个字节的数据:

缓冲区

UDP只有接收缓冲区,没有发送缓冲区:

UDP的socket既能读,也能写,这个概念叫做 全双工

大小受限

UDP协议首部中有一个16位的最大长度。也就是说一个UDP能传输的数据最大长度是64K(包含UDP首 部)。

4.2.3基于UDP的应用层协议

  • NFS:网络文件系统
  • TFTP:简单文件传输协议
  • DHCP:动态主机配置协议
  • BOOTP:启动协议(用于无盘设备启动)
  • DNS:域名解析协议

当然,也包括你自己写UDP程序时自定义的应用层协议。

4.2.4扩展问题

这是一个经典面试题:

  1. UDP本身是无连接,不可靠,面向数据报的协议,如果要基于传输层UDP协议,来实现一个可靠传 输,应该如何设计?
  2. UDP大小是受限的,如果要基于传输层UDP协议,传输超过64K的数据,应该如何设计?

以上两个问题答案类似,都可以参考TCP的可靠性机制在应用层实现类似的逻辑:

例如:

4.3TCP/UDP对比

我们说了TCP是可靠连接,那么是不是TCP一定就优于UDP呢?TCP和UDP之间的优点和缺点,不能简单,绝对的进行比较

归根结底,TCP和UDP都是程序员的工具,什么时机用,具体怎么用,还是要根据具体的需求场景去判定。

例如我们在学校的机房里,可靠性就比较高,我们为了追求速度会使用UDP来进行各个电脑间的通信。

5.网络层重点协议

在复杂的网络环境中确定一个合适的路径。

5.1IP协议

协议头格式如下:

6.数据链路层重点协议

6.1认识以太网

6.1.1以太网帧格式

以太网数据帧 = 帧头 + 载荷 + 帧尾

帧头(目的地址 源地址 类型) 载荷(完整的 IP 数据报) 帧尾()

以太网的帧格式如下所示:

6.1.2 IP地址 和 mac地址有啥区别吗?

想必大家都有一个疑问吧,那就是既然有了 IP地址 ,为什么还要创造一个 mac 地址呢?

这其实是一个悲伤的故事,加入只有一套地址体系 (比如 IP 和 以太网都是用 IP地址/mac地址) 是完全可以玩得转的
但是最开始大佬们研发初代的协议栈的时候,研发 网络层协议 和 研发 数据链路层协议 的大佬是两伙人,他们各自独立的研发出了一套地址体系。最后双方大佬各用各的地址,于是就演化成了两套地址体系,相互配合使用。

那么 IP 和 mac 是如何配合的呢?

IP 用来描述争个整个传输过程的起点终点。 mac 则是用来描述 两个相邻节点,起点终点(各司其职)

IP做的事情:

mac做的事情:

总结:IP 描述的是 “初心”,最初从哪来到哪去,最初的目标是啥?
mac 描述的是 当前阶段 的任务。

6.2认识MTU(对于较大的IP数据包要进行分包)

MTU相当于发快递时对包裹尺寸的限制。这个限制是不同的数据链路对应的物理层,产生的限制。

6.2.1MTU对IP协议的影响

由于数据链路层MTU的限制,对于较大的IP数据包要进行分包。

6.2.2MTU对UDP协议的影响

让我们回顾一下UDP协议:

6.2.3MTU对于TCP协议的影响

让我们再回顾一下TCP协议:

MSS和MTU的关系

6.3ARP协议

虽然我们在这里介绍ARP协议,但是需要强调,ARP不是一个单纯的数据链路层的协议,而是一个介于 数据链路层和网络层之间的协议;

6.3.1ARP协议的作用(直到 ip 通过 ARP 来返回 mac)

ARP协议建立了主机 IP地址 和 MAC地址 的映射关系。

6.3.2ARP协议的工作流程

7.总结

7.1数据链路层

7.2网络层

7.3传输层

7.4应用层

感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘

举报

相关推荐

0 条评论