0
点赞
收藏
分享

微信扫一扫

远程协助,打工人的数字生活私人医生

_铁马冰河_ 2024-12-12 阅读 16
linux网络

文章目录

理解一下,打通一下文件和socket的关系

网络服务都是进程,在内核中叫做tast_struct
每个打开的文件都要有文件描述符
进程有文件描述符表

文件描述符指向strcut file
file结构体中有个 private_data指针
如果这个文件是个网络文件,该指针就会指向struct socket文件

而struct socket文件也有指针回指sturt file
在这里插入图片描述
也就是在网络里随时想返回来找文件也能找到。

以前讲过一切皆文件,最终整个网络文件挂接到struct file下,应用层看待它一切只需要按照文件描述符就能找到这个文件的struct socket

所以struct socket里有一个wait_queue_head_t wait是什么呢?

在这里插入图片描述
记不记得对应的进程阻塞等待时,要把自己的PCB链入到指定的数据结构里,所以如果网络读取数据不就绪,只要讲进程挂接到wait_queue里就可以了。

socket里还有一个 方法集proto_ops ops,和struct file也有方法集f_op
在这里插入图片描述

在这里插入图片描述
我们发现socket 里还有 struct sock* sk
指向了strcut sock 这只是网络的开始
在这里插入图片描述

struct file 指向strcut socket是从文件到网络的过度

sock里包含接受和发送两个队列
以UDP 和TCP为例,走到这里其实到网络了

struct sock* sk 看起来是指向struct sock但实际上他并没有指向sock,当你创建tcpsocket时他指向的是struct tcp_sock,当你创建UDP套接字时其实系统中创建的是udp_sock
在这里插入图片描述
只不过这两个结构体中开头都包含了sock结构体

在这里插入图片描述
我怎么知道我指针sk指向的是tcp还是udp呢?

在这里插入图片描述
socket中有个flags 或者 type可以区分socket类型。

未来我要使用tcp的其他属性,我只需要(strcut tcp_sock*)sk - > 就能访问到tcp套接字里面的内容了。
在这里插入图片描述
所以他的本质就是C语言的多态。
当我们在网络中收数据发数据到了tcp或udp的套接字最开始就是sock,而sock里面就有sk_buff的接受和发送队列。

在这里插入图片描述
此时通过网络上层把数据通过文件描述符把数据交给下层再交给tcp_sock就完了吗?
还没完

问题
网络协议栈层状结构,什么叫做协议栈啊
所谓的协议栈的本质
Linux内核是用C语言写的,所谓的协议栈本质就是

  1. 用特定数据结构表述的协议
  2. 和特定协议匹配的方法集!

文件stcut file本来就有自己的方法集,当底层指向的不是磁盘而是网络,则文件指向的方法是网络相关的方法。

struct socket 也有方法集

在这里插入图片描述
这俩有什么区别呢
未来file提供的方法一部分直接指向网络方法了,file方法最终要解决的是对上的问题,因为用户数据在应用层,应用层数据一定要通过fd拷贝到我们的套接字所对应的接受和发送队列中,他要给你形成一个节点,把他连入到队列中。
首先把上层数据交给下次,交给队列。

strcut socket里面的方法呢主要是对下的,也就是说提供的connect ,sendmsg,因为sendmsg没有发送缓冲区,所以你把数据交给下层看起来好像在队列里,其实我们将来使用sendmsg不用file里的方法,而用socket的方法直接就把数据发出去了,但如果是tcp的话数据先放到队列里,socket里提供了网络建立连接的一些方法,实际上底层sock里还有对应的方法集,每一层都有对应的方法集,要么是对数据加工处理,要么是把数据拷贝到底层的,因为tcp根本没有把数据发出去,tcp这些所有方法集不是把数据发到网络而是想办法把数据交到下层。

所以呢无论是文件中,还是网络套接字里,还是未来tcp udp的套接字里,各自提供各自层的方法,tcp,udp根本不会把数据send发送到网络里,他应该把数据交给下一层,所以对应的所有函数指针指向的方法由对应的协议栈给我们提供方法集。

曾经说过我们对应的OS中一定同时收到大量的报文,不管tcp 还是Udp,上层不只一个网络服务,A进程想发,B也想发。

每一个文件描述符就对应一个Struct file,对应一个stcut socket,对应一对接受发送缓冲区。
在这里插入图片描述
我们的OS内可能同时存在很多报文,不要觉得tcp是面向字节流,所有报文都是字节流,不一定
问题是OS中数据都是一个个报文,所以OS中要不要把多个报文管理起来?
我收到的报文里上层不读,所以OS积压了很多报文。
服务器收到多个报文,而报文是要被管理的
如何管理呢?
先描述,在组织
每一个在网络中的报文他的数据结构叫做sk_buff
在这里插入图片描述
为什么还有个锁呢?
因为接受和发送的过程本质在内核中属于CP模型

sk_buff里四个指针会互相配合指向一段内存空间
在这里插入图片描述
在这里插入图片描述
所以如果我今天收到了一个报文,head代表报头的开始,tail代表报文的结束,end空间的结束,data代表数据的开始
所以在不同的层,在网络中,sk_buff结构体叫做先描述,然后每一个sk_buff收到的报文就在对应的内存空间中,我们把这个sk_buff称为一个内核级别报头
在这里插入图片描述
在这里插入图片描述

所以我们经常说要把报文经过传输层交给
下层,从下层交给上层,本质上是让sk_buff的结构在层和层之间进行流动,所以流动时向下层交付时,我们要封装报头本质就是让head指针继续根据下层协议报头长度,让指针往上走,这叫做封装的过程
在这里插入图片描述

如果解包根据每层协议不同的方法来让指针根据每层报头的大小格式了,让head指针往下走,此时叫做解包在这里插入图片描述

所以封装和解包本质上只要进行移动指针就可以!!

任何一层报文无非就是报头和有效载荷,每一层无非就是根据报头协议字段来移动head,比如第一个报头是tcp,我们指向当前的一个报文,head指向的是Tcp报头,然后根据tcp前20字节,根据报文长度我就可以直接找到数据区,此时报头就确定出来了,此时头空间有效载荷就出来了。
如果有数据新增移动尾指针就可以了
所以他是通过指针方式来对buff管理的。

所以先描述这个sk_buff结构体 用4指针管理,然后所有的报文在网络层大家是一块的,但到传输层之后呢我们就要把报文分发给每一个不同的文件描述符了
在这里插入图片描述

所谓的分发就是把sk_buff在组织到对应的缓冲区里
在这里插入图片描述
此时我们就可以得到对应的报文了。

最终告诉结论就是 一切皆文件,我们的网络套接字本质上也是文件。

将来你读取数据时本质通过这一大堆链路,找到receive_queue,从里面读取一个或多个sk_buff,然后把数据交给上层。

在这里插入图片描述
这个recvive_queue是链表,并不是我们以前讲的数组啊?
并不是,但在逻辑上认为他是个数组,好理解,这就是理论和现实的差别!

提问
是不是,传输层、网络层、数据链路层的解包操作都在接收缓冲区中操作,不需要繁琐的拷贝,只是指针移动
解释
也就是对sk_buff在链路层交给网络层就进行指针移动,后续交给上层继续指针移动不发生拷贝。

还有一点就是tcp中accept 创建一个链接时, 要重新分配文件描述符,重新分配stuct file,重新stcut socket,重新分配收发队列,重新搞sk_buff
所以我们说建立连接是有成本的,维护连接是有成本的,因为要在内核创建大量数据结构。

网络层

结论
ip协议的本质工作:提供一种能力,将数据跨网络从A主机送到B主机!

ip协议他的核心工作是真正的要把ip报文发送到网络中了,Tcp报文并没有直接到网络里,他是包裹在ip里面被发出来的。

ip协议有这种能力将数据跨网络从A主机送到B主机,可是用户需要这种能力吗?

能力本身不是100%做到的,上层用户要的是将数据可靠的跨网络从A送到B。

所以IP协议只要将来能把数据跨网络发送,以现在网路情况送过去概率非常高,但不是100%的,所以传输层提供策略(超时重传等),下层提供能力,ip和tcp一结合就可以保证每次都能发送成功。

ip协议

ip协议他的工作就是经过一堆路径选择把数据送到目标主机

前置认识

常识:从A主机到B主机发报文需要跨很多路由器

在这里插入图片描述

前提每台主机
a:要对所有的主机进行标识。
源ip,目的ip来标识源主机和目的主机
ip地址分成私有ip,公网ip
我们今天两天主机通信都默认公网ip通信
所以我们有了唯一性标识在通过路径选择再去把数据转发到目标主机才有可能。

b: 去一个地方玩要分两个阶段
1。去目标城市
2。去目标地点

ip地址的构成 实际上由两部分构成
ip = 目标网络 + 目标主机!

每台主机都在一个子网中
从A发到B,要经过路由器转发,跨越子网
所以走的时候一定是先到达B主机所在的网络(先到达目标网络),接着想办法把报文交给目标主机
在这里插入图片描述
先到目标网络,再到目标主机,凭什么啊?
凭的就是路由器的转发

我们活在一个被精心设计的世界中 !
学号并不是一个单纯的数字,标识你这个人
学号也有构成,是被精心设计过的。
学号 = 学院编号/专业编号/班级编号/学生编号
网络世界也是被精心设计过得。

学号简化为
学号 = 学院 / 学号
方便表述。

我们都有学院群
每一个学院都有一个学生会主席
在这里插入图片描述

学生会主席自己有没有拉群啊
他们肯定也一定都在一个群里
在这里插入图片描述
计算机学生009捡到了钱包中有个只能看到学号的学生卡432008
你要把这个钱包归还给人家,归还钱包本质是查找,查找本质是排除!
如果我一个一个在食堂门口问就是线性遍历,效率太低!
我就在学院的计算机群里,计算机群里不是有学生会主席吗,他应该根其他学院也拉了群啊,计算机学生会主席他应该知道其他学院的学号啊,你不知道当什么学生会主席啊。
所以拿着这个学生卡的照片发给计算机群里,@计算机主席,我虽然不知道432是哪个学院的,但我知道他一定不是我们计算机学院的,计算机主席一看432,432不是电气学院的吗,他虽然不认识这个学生,但他认识学院号,他就把这个照片发到他的群里面,@了电气的学生会主席,询问是不是电气学院的啊?电气学院学生会主席也要对他的学生有所了解,此时电气主席就把照片转发到电气群,@了小美。
在这里插入图片描述
为了能让小美找到我,这个消息还会带上我的学号和电话。

为什么归还的速度变快了??

因为我把这个报文转给学生会主席本质是我淘汰了计算机院的一群人,计算机主席把数据转发到学生会群里面@电气主席,本质是淘汰了剩下其他的学院,查找的本质是排除,所以建立群把我们每一个人按照这种方式
学号 = 学院+学号各自拉群,这种方式速度变快,本质是因为以前一次淘汰一个人,今天一次淘汰一群人
排除的效率高了!!!

所以我们把这种地址叫做ip地址在这里插入图片描述
123009叫做源ip
在这里插入图片描述
我要去的目的ip叫做432008.
图中局域网 还有局域网主机
在这里插入图片描述
计算机学生会主席叫做 局域网出口路由器

把学生会主席的群叫做公网
在这里插入图片描述
所以把数据通过局域网转发到公网当中然后公网当中每一台路由器天然认识其他在公网里所有路由器,所以路由器可以转发找到小美
所以这次查找时思路是先找到目标网络,也就是小美所在的群,小美所在的局域网,
然后再由目标网络转到目标主机
在这里插入图片描述
所以这样去搞就可以提高效率了。

此时就可以跨网络传输了。

所以ip地址为什么要分成这样呢?
在这里插入图片描述
我们又为什么要这样呢?
在这里插入图片描述

因为本质上我们路上查找时效率高,一次可以排除很多东西

所以ip = 目标网络 + 目标主机是为了构建网络的时候,为我们将来高速定位一台主机,提供基础保证!!

那校学生会主席会不会也拉一个群呢?
有清华的,有北大的,会不会拉群呢?
所以网络就不断层层叠叠之下越来越大。

所以记住两个就可以了
1每台主机都要有唯一标识
2 ip地址不要简单理解成四字节数据,要理解为ip = 目标网络 + 目标主机

把这个换钱包的故事记住

ip协议的报头

其他话题

举报

相关推荐

0 条评论