当前位置: 首页 > news >正文

【Linux网络编程】数据链路层 高级IO模型

文章目录

  • 一、数据链路层:
    • 1、数据链路层报文解析:
    • 2、局域网通信:
    • 3、MSS与MTU:
    • 4、ARP协议:
      • 工作原理:
      • ARP报头解析:
      • 模拟一次ARP协议:
    • 5、其他重要协议或技术
      • DNS:
      • 域名:
      • ICMP:
      • NATPT:
      • 代理服务器:
  • 二、高级IO:
    • 1、重新理解IO:
    • 2、五种IO模型:
      • 阻塞式:
      • 非阻塞轮询:
      • 信号驱动IO:
      • 多路转接:
      • 异步IO:
    • 3、非阻塞代码理解:

一、数据链路层:

IP层解决在公网中的不同主机之间的数据交付问题,本次所讲的数据链路层所解决的就是在同一个局域网中,直接相连的主机(不仅仅是电脑和电脑直接,也可是电脑和路由器之间)之间的,进行数据交付的问题

Mac地址:区分在同一个局域网中,区分特定主机的地址
Mac帧:带着Mac地址的数据包

1、数据链路层报文解析:

在这里插入图片描述

对于一个协议,那么理解这个协议需要理解两点重要的

  1. 如何进行解包
  2. 如何进行分用

如何解包:
定长报文,当数据链路层得到一个报文后,直接读取前面的字节数量就能够直接得到报头了,然后就能够直接进行报文和有效载荷的分离了

如何分用:
当读到报头后,在报头中有一个字段叫做类型,通过这个类型进行分用,判断是何种,比如说:0800就是IP数据包,0806就是ARP请求/应答,8035就是RARP请求/应答

2、局域网通信:

每台主机在局域网上都要有自己唯一的一个标识

当老师在讲台上进行讲话的时候,对下面的人说:张三,你怎么没交作业,此时是所有人都会听到这个信息,拿到这个报文,然后进行报头的比对发现说的不是我,就将整个报文的丢弃,但是张三进行报文解析的时候发现讲的就是我,那么就会做出反应,就会对老师说:我昨天给你了啊,那么之后老师就会给予回应而不是别人,但是别人会听到张三的回答,但是并不会对其进行反应,因为张三是对老师进行回答的

在这里插入图片描述

如上这种向当前局域网所有主机发送消息,但是会进行比对主机这种局域网通信就是以太网通信,所以说:局域网通信的过程,其实是有很多吃瓜群众的

数据碰撞

如果在一个局域网中有多个主机在进行发送数据,那么就会在这个局域网中进行数据碰撞,这样其中的光电信号,波信号就会混乱了,就会导致接收的数据出现问题

但是一个主机怎么知道什么时候会发生数据碰撞呢?当在一个教室里面进行讲话,我自己也会听到我自己的声音的,所以一个主机将数据发出了后也会收到自己的数据的,那么就能够知道当前局域网有没有发生数据碰撞

在系统中有发送主机都要执行的碰撞避免的算法,这个算法是由以太网的驱动程序自己定的,当发生了数据碰撞后,就延迟发送,错峰发送

正确看待局域网:

局域网内的数据是能够直接通信的

任何主机都可以向局域网里发消息,但任何一时刻只允许一台主机向一个局域网中发送消息,所以局域网是所有主机的共享资源,所以要保证所有主机在使用这个共享资源的互斥访问,这个操作并不是通过加锁完成的,是一旦发生错误,就重新发送资源,相当于这个主机在发送资源的时候没有其他主机使用这个网络资源,出问题再说,所以局域网可以看做多台主机共享的临界资源

交换机:

在这里插入图片描述
交换机是一种用于连接多台设备,并让它们在局域网内高速交换数据的网络硬件,交换机将局域网一分为二,然后当左侧发生碰撞后,交换机能够检测到发生了碰撞,此时就拦截左边的数据继续往右传播,所以就不会影响右边了,此时右边还是能够进行数据的转发的,所以交换机能够:划分碰撞域,减少局域网碰撞

3、MSS与MTU:

  • MTU(最大传输单元)
    层级:工作在数据链路层,针对的是数据帧
    定义:指数据链路层帧结构中,数据部分(即封装的网络层数据包)的最大字节数,不包含链路层自身的头部(如以太网头部 14 字节、CRC 校验 4 字节)
    以太网:默认 MTU=1500 字节

  • MSS(最大分段大小)
    层级:工作在传输层(仅 TCP 协议使用,UDP 不涉及),针对的是TCP 分段
    定义:指 TCP 分段中,应用数据部分的最大字节数,不包含TCP头部(通常 20 字节,若带选项则更多)和IP头部(通常 20 字节,若带选项则更多)
    核心作用:TCP 通过MSS限制单个分段的应用数据大小,确保封装后的IP数据包不超过底层链路的MTU(避免 IP 分片,减少网络开销)

计算示例:
假设 IP 头部和 TCP 头部均为最小长度(无选项,各20字节),则:MSS = MTU - IP头部长度(默认20)- TCP头部长度(默认20),以最常见的以太网 MTU=1500 为例:MSS = 1500 - 20 - 20 = 1460字节这也是互联网中TCP连接的默认MSS值

4、ARP协议:

在这里插入图片描述
在之前的学习中,我们了解到了:所谓的数据发送到网络,本质上是通过无数个子网实现的,在发送报文中,通过子网进行跳跃到路由器中,然后路由器在网络层根据ipdst判断是不是在当前局域网的,如果不是就重新封包(此时ipsrc被更改为当前路由器的ip)然后继续路由,直到交到路由器的目标主机所在的同一个局域网

当目标主机所在的局域网中的路由器拿到报文后,在网络层发现目标主机是和我在同一个局域网的,那么路由器重新封装Mac帧,然后在局域网中进行广播,接着就是局域网的通信原理了
在这里插入图片描述
但是此时有个问题:在填目的地址的时候,路由器怎么知道目标主机的Mac地址呢?——此时就轮到arp协议登场了

ARP:在 TCP/IP 协议中,数据包的传输需要知道目标主机的 MAC 地址,而 IP 地址只是逻辑地址,不能直接用于数据包的传输。ARP 协议在网络层和数据链路层之间起着桥梁作用,确保数据包能够正确地传输到目标主机

工作原理:

当主机A要向主机B发送数据时,会先查看本地的ARP缓存表,看是否有主机B的IP地址对应的MAC地址。如果有,就直接使用该MAC地址进行数据封装和发送;如果没有,主机 A 会发送一个ARP请求广播包,该报文中包含源主机A的MAC地址和IP地址,以及目标主机B的IP地址,目的MAC地址为全F为广播,局域网上的所有主机都会收到该ARP请求,只有主机B会匹配自己的IP地址,然后将自己的MAC地址封装在ARP响应报文中,以单播方式发送给主机A。主机A收到ARP响应后,会将主机B的IP地址和MAC地址添加到自己的ARR缓存表中,以便后续通信

ARP报头解析:

ARP协议是属于MAC帧上层的,但是是归属到数据链路层的
在这里插入图片描述
在这里插入图片描述

报头解析:

  • 硬件类型指链路层网络类型,1为以太网
  • 协议类型指要转换的地址类型,0x0800为IP地址
  • 硬件地址长度对于以太网地址为6字节
  • 协议地址长度对于和IP地址为4字节
  • op字段为1表示ARP请求,op字段为2表示ARP应答
  • 发送端和目的就是我们的路由器和目标主机

模拟一次ARP协议:

在这里插入图片描述
首先,当路由器R接收到了别的路由器跳转来的报文,然后进行解析,此时比对报文中的目的IP地址,发现目的IP地址的网络号是当前子网,那么就证明要找的主机B就在当前子网,此时在本地的ARP缓存表进行查看,发现没有,那么就会进行一次广播:

在这里插入图片描述

前三个是按照数据链路层的报文来填写,当后面的数据填完后再添加前面三个Mac帧

目的地址不知道填全F表示广播
原地址填写当前路由器的Mac地址
帧类型填写0806表示ARP请求

硬件类型填1,表示以太网
协议类型是IP地址转化为MAC地址,所以填0800
硬件长度就是6,协议地址长度就是4
然后OP字段是1
发送端的以太网地址是谁呢? 就是MacR
发送端的IP地址就是IPR
目的以太网地址不知道,填写广播为全F
目的IP就是IPB

填写完后就在局域网中进行广播,此时每台主机都会收到当前报文,在数据链路层中收到后,查看帧类型,发现是0806为ARP报文后向上交付给ARP层,接着查看OP字段,发现是1是请求,此时在看IP地址,发现如果不是当前IP,就将报文丢弃,如果是当前IP,如这里的主机B,就进行应答:(此时就会将自己的Mac地址返回)

在这里插入图片描述
之后就将这个报文定向发送给路由器,这样当路由器拿到当前报文后,就能够拿到MacB的Mac地址了

在ARP的过程中,收到的任何ARP报文,都是先看OP,OP决定了ARP的类型:请求或者应答,如果是请求,我们看的是目的MAC地址和目的IP;如果是应答,我们看的是发送端的MAC地址和发送端的IP,看看这两个是否相等

主机的mac地址和ip地址,会被主机临时缓存起来

  1. ARP只有在缓存失效的时候,才会进行
  2. 我可以通过我的IP和子网掩码,得到我的网络号,然后拼接IP地址,ping所有的主机,得到所有主机的IP和mac
  3. 如果我收到多次同样的arp应等我会以最新的为准

5、其他重要协议或技术

DNS:

这是域名解析服务:我们访问网站本质上是通过一串数字访问的,但是这样不方便访问,那么就有了域名,自然也就有了域名解析服务,这就叫做DNS

在这里插入图片描述

域名:

这里以www.baidu.com为例:
.com:一级域名,表示一个企业域名,同级的还有“net”(网络提供商),“org”(非盈利组织)等
baidu:二级域名一般都叫做公司名
www:习惯用法,可以不写

有个经典面试题:
当在浏览器中输入一个URL后按回车会发生什么

  1. 输入 URL ——>浏览器解析 URL 并校验;
  2. DNS 解析 ——>域名转 IP 地址;
  3. TCP 三次握手 ——>建立可靠连接;
  4. 进行协商加密
  5. 发送 HTTP 请求 ——>浏览器向服务器要资源;
  6. 服务器处理 ——>返回 HTTP 响应(如 HTML);
  7. 浏览器渲染 ——>解析 HTML/CSS/JS,生成可视化页面;
  8. 网络四层的作用

以上是粗略地进行讲解,还需要一个步骤一个步骤更细分

ICMP:

这是网络层的协议:主要是用来确认报文是否丢失,是在IP协议之上的,当存在ICMP协议的时候,如果主机A发送数据给主机B,但是数据不可达,那么路由器就会返回给主机A一条信息,告诉我们信息不可达
在这里插入图片描述

作用:

确认IP包是否成功到达目标地址
通知在发送过程中IP包被丢弃的原因
ICMP也是基于IP协议工作的.但是它并不是传输层的功能,因此人们仍然把它归结为网络层协议
ICMP只能搭配IPv4使用,如果是IPv6的情况下,需要是用ICMPv6

其中,网络命令ping就是基于ICMP的,不光能验证网络的连通性,同时也会统计响应时间和TTL

这里也有一个面试题:
telnet对应的端口号是23,ssh 对应的端口号是22,那么ping对应的端口号是多少呢?
ping 命令基于ICMP,是在网络层,而端口号是传输层的内容,在 ICMP 中根本就不关注端口号这样的信息,所以 ping 根本没有端口号,ping 命令实际是绕过了传输层的直接访问底层 ICMP 协议的一种做法

NATPT:

在理解这个之前首先要知道什么是NAT技术,这部分在上一章IP协议中有讲到IP协议

但是还有一点未讲到:
当公网返回私网报文的时候,此时肯定会有很多报文,这些响应报文的目的IP都是当前路由器的WAN口IP,我们怎么将这些报文和那些主机对应起来呢?
在路由器中有一张表,叫做NAT转换表:当有报文转发出去的时候,会将内网中的源主机的IP和端口目标主机的IP和端口路由器的WAN口IP和端口目标主机的IP和端口进行映射形成KV式的哈希表

在这里插入图片描述
因为IP和端口号的唯一性,所以这个映射是唯一的,并且即使主机B也发送报文,那么映射后的WAN口IP的端口号一定是不一样的,这样就能够保证映射的唯一性

NAT在替换的时候,不仅仅会替换IP,也会替换端口号,这样就保证了映射表中的键值对是双向的,即映射双方互为键值,所以,当数据回来的时候,我们的数据就知道是给哪个目的IP,哪个目的端口号,去查键值对,就能锁定内网当中的目标主机了

代理服务器:

代理服务器的功能就是代理网络用户去取得网络信息,代理服务器又分为正向代理和反向代理

正向代理:
客户端并不直接访问目标服务器,而是先访问代理服务器,由代理服务器代替客户端去访问对应的目标服务器,并将目标服务器的响应结果返回给客户端
当多台主机都要访问外网的同一个资源,那么正向代理服务器就可以将对应的资源缓存到本地,此时当其他主机要访问该资源时,直接在正向代理服务器就可以获取,而不需要再次进行外网访问
在这里插入图片描述

反向代理:

当反向代理服务器收到客户端的数据请求后,就会将我们的数据请求转发给其所代理的某台服务器进行数据处理,然后再将数据处理的结果返回给客户端,它不做任何业务的处理,只负责将请求推送到后端的指定主机,用户不需要知道目标服务器的地址,用户只需要访问反向代理服务器就可以获得目标服务器提供的服务
在这里插入图片描述
正反向代理服务器的区别
正向代理是客户端的代理,帮助客户端访问其无法访问的服务器资源的,而反向代理则是服务器的代理,帮助服务器做负载均衡、安全防护等工作的
正向代理中,服务器不知道真正的客户端到底是谁,服务器认为正向代理服务器就是真实的客户端,而反向代理中,客户端不知道真正的服务器是谁,客户端认为反向代理服务器就是真实的服务器

NAT和代理服务器的区别
NAT 和代理服务器都是代替我们向服务器发起数据请求的:

  • 从应用上讲,NAT 设备是网络基础设备之一(必须的),解决的是 IP 不足的问题。代理服务器则是更贴近具体应用,比如通过代理服务器进行翻墙,另外像迅游这样的加速器,也是使用代理服务器
  • 从底层实现上讲,NAT 工作在网络层,直接对 IP 地址进行替换,而代理服务器往往工作在应用层
  • 从使用范围上讲,NAT 一般在局域网的出口部署,代理服务器可以在局域网做,也可以在广域网做,也可以跨网
  • 从部署位置上看,NAT 一般集成在防火墙,路由器等硬件设备上,代理服务器则是一个软件程序,需要部署在服务器上

二、高级IO:

1、重新理解IO:

IO也就是Input和Output
这里通过read和write来理解:
当调用read的时候,如果接收缓冲区中没有数据,那么read就会进行阻塞
当调用write的时候,如果发送缓冲器写满了,那么write也会阻塞

当这些读和发送这种IO的函数不是直接将数据发送到网络上的,而是拷贝到发送或者接收缓冲区,在由TCP自主发送,这些本质是拷贝函数,但是这些拷贝函数大部分时间都在等,所以IO本质是 等+拷贝,为什么要等呢?对于read,需要等待接收缓冲区中有数据,对于write,需要等待发送缓冲区中有空位,所以在拷贝之前需要条件成立

对于高效IO:单位时间内,IO中等的比例越小,IO的效率就越高,所以几乎所有提高IO效率的本质都是让等的比重减小

2、五种IO模型:

哪五种:

  1. 阻塞式等待
  2. 非阻塞式等待,非阻塞轮询查看是否读写事件就绪
  3. 信号驱动,就是当读写事件就绪的时候通知我们
  4. 多路转接,多路复用
  5. 异步IO

这里通过一个故事来理解:

  • 张三喜欢钓鱼,张三钓鱼的时候,抛竿后一直看着鱼竿进行等待,直到鱼咬钩后提鱼竿,这就是阻塞式
  • 李四钓鱼的时候,抛竿后就在一边搞其他事,每过一定时间后就看鱼竿有没有鱼咬钩,这就是非阻塞式
  • 王五钓鱼的时候,在鱼竿上加上一个铃铛,然后进行抛竿,之后不用每过一定时间去看,而是直到铃铛响后就直接钓起来,这就是信号驱动
  • 赵六钓鱼的时候,搞多个鱼竿,然后将鱼竿都抛进海里,然后在岸上找了个视野开阔的位置坐着,眼睛同时盯着这几根鱼竿的动静。他既不用像张三那样紧盯着一根竿子啥也干不了,也不用像李四那样频繁起身挨个检查,而是就坐在原地,一旦看到某一根鱼竿的鱼线往下沉、浮漂有动静 —— 也就是这根鱼竿 “有鱼咬钩” 的信号就绪了,就立刻起身过去提这根竿子;等处理完这根竿子的情况,无论是钓上鱼还是重新抛竿,他又坐回原位,继续同时盯着所有鱼竿,等待下一根有动静的竿子,这就是多路转接
  • 田七钓鱼的时候,叫了一个小王,给了小王桶,电话,钓竿,然后跟小王说:你钓鱼,有了之后直接给我送过来,其中田七是钓鱼的发起者,并没有进行参与,只需要向 “执行者”(小王,对应操作系统内核或异步 IO 框架)提交 “钓鱼任务”(IO 请求),并告知结果交付方式(对应回调函数或通知机制),之后就能去处理其他事务,完全不用等待钓鱼过程,这就是异步IO

阻塞式:

在这里插入图片描述

当recvfrom读取数据的时候,如果数据没有准备好,那么就会阻塞在系统中,本质是OS把PCB从运行队列中拿下来,当有数据了之后,把进程唤醒,在进行内核到用户的数据拷贝

非阻塞轮询:

在这里插入图片描述
recvfrom可以设置成非阻塞的,此时每过一定时间都会去问有没有数据,不会一直阻塞等待,而是返回EWOULDBLOCK,当检测成功的时候,就和阻塞式一样了进行内核到用户的数据拷贝

信号驱动IO:

在这里插入图片描述
内核将数据准备好的时候, 使用SIGIO信号通知应用程序进行IO操作

多路转接:

在这里插入图片描述
之前有讲过IO = 等+拷贝,在这里由select系统调用进行等,等待就绪后通知recvfrom,recvfrom就只需要进行读即可,这里最大的特点就是他们会一次性等待多个文件描述符

异步IO:

在这里插入图片描述
调用接口后直接返回,应用层做自己的事 OS等待数据,当OS等待成功后帮我把数据从内核拷贝到用户,之后再进行数据处理

3、非阻塞代码理解:

接下来实现一下网络套接字版本的非阻塞IO:
在这里插入图片描述
fd:要操作的文件描述符(必须是已打开的有效文件描述符,如通过 open 或 socket 获得)
cmd:操作命令(核心参数,决定 fcntl 执行的具体操作)

对于cmd:
F_GETFL:获取当前文件状态标志
返回值包含文件的访问模式(O_RDONLY、O_WRONLY、O_RDWR)和其他标志(如 O_NONBLOCK、O_APPEND 等)
注意:访问模式(O_RDONLY 等)需通过 O_ACCMODE 掩码提取(直接判断可能不准确)
F_SETFL:设置文件状态标志
可修改的标志:O_NONBLOCK(非阻塞模式)、O_APPEND(追加模式)、O_ASYNC(异步 I/O 通知)等
不可修改的标志:访问模式(O_RDONLY 等)、O_CREAT 等(需通过 open 重新打开文件修改)
F_GETLK:检查是否存在与目标锁冲突的锁
第三个参数:struct flock *lock(传入要检查的锁信息,返回冲突锁的信息)
F_SETLK:设置锁(非阻塞)
若无法获取锁(如被其他进程占用),直接返回 -1 并设置 errno = EAGAIN 或 EACCES
F_SETLKW:设置锁(阻塞)
若无法获取锁,会阻塞等待直到锁可用(或被信号中断)
F_DUPFD
复制一个现有的描述符

如下是非阻塞轮询的代码示例:

#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include<cstring>using namespace std;void SetNoBlock(int fd)
{int fl = fcntl(fd,F_GETFL);if(fl < 0){perror("fcntl");exit(1);}fcntl(fd,F_SETFL,fl | O_NONBLOCK);
}int main()
{SetNoBlock(0);char buffer[1024];while(true){cout << "Please Enter# ";fflush(stdout); ssize_t n = read(0,buffer,sizeof(buffer)-1);if(n > 0){// 把读上来的数据当做字符串buffer[n] = 0;cout << "读上来的数据:" << buffer << endl;}else if(n == 0){cout << "读取结束" << endl;}else{if (errno == EWOULDBLOCK){cout << "还没有数据,重新尝试" << endl;sleep(1);}else{cout << "读取失败 n = "  << n << endl;cout << "错误码: " << errno << " " << "错误描述: " << strerror(errno) << endl;}}}return 0;
}

在这里插入图片描述

http://www.dtcms.com/a/396276.html

相关文章:

  • 网站怎么做下拉刷新合肥仿站定制模板建站
  • 程序员做项目网站关于中秋节网页设计实训报告
  • 16.Linux RAID 存储技术
  • 网站摇奖活动怎么做只做特卖的网站
  • LLM安全基础入门:揭开大模型安全的面纱
  • 响应式外贸网站案例做公众号主页面的有哪些网站
  • 建企业网站需要多少钱网站建设摊销会计分录
  • 手机与pc的网站开发中国好公司网站建设
  • 网站建设公司好哪家好免费网站推广工具有哪些
  • 无锡外贸网站制作宜城网站定制
  • 数据图表展示网站茶叶 企业 网站建设
  • 南京建设工程网站石家庄营销推广网站
  • 太原网站制作最新招聘信息宿迁哪里做网站
  • 如何介绍设计的网站模板广州互联网网站建设
  • 静态网站怎么维护局网站内容建设考核
  • 麻城建设网站浙江城乡建设局和住建局
  • 手机开发商东莞优化哪家好
  • LVS负载均衡技术全解析
  • OpenSpot 2.0.3 | 国内外音乐下载免费,需要特殊网络,搜索最好用繁体中文
  • 【ROS2】Beginner: Client libraries - parameters / ros2doctor / pluginlib
  • 中文域名网站有哪些免费网站建站塔山双喜
  • 基于JavaSwing的扫雷(含操作手册和设计文档)
  • 在电脑上哪里可以做网站wordpress 安装语言设置中文
  • 算法一刷 数组(上)
  • 德州哪里做网站做网站美工
  • 甘肃省第八建设集团公司网站Wordpress 搜索热词
  • 两个网站如何做端口映射郴州网站建设软件定制开发制作
  • 天津微网站建设智慧团建注册登录入口下载
  • 第十周SSRF漏洞
  • Pyside6 + QML - 信号与槽06 - 一个信号触发多个函数