网络基本概念认识(2)

目录

前言:

局域网+协议

MAC/IP地址

Socket编程

TCP/UDP

网络字节序


前言:

本文同样作为博主的二刷网络课程的文章,主要涵盖的主题还是网络基本概念的认识,从上一篇文章遗漏的点加上引入的一些知识点共同组成当前的知识点。

在这篇文章收尾之后,我们就会开始愉快的TCP UDP IP ARP Cookie Session......之旅,所以在面临风暴之前,我们还是尽可能的将网络基础部分理解吧。

那么本文的重点在于:局域网的分类,第二次认识协议,认识MAC地址IP地址,理解网络通信中的socket编程等

当然了,重点在于...其实都是重点哈哈哈。

那么废话不多说,我们直接进入主题吧!!


局域网+协议

对于局域网和协议来说,咱们要理解的实际上没有那么多,所以博主这里将两个知识点放在了一起。

对于局域网来说,是有很多很多种的,而网络的诞生就像武功问世一样,不同的人整出了不同的帮派,只有那些最牛逼的帮派才能活到最后。

所以局域网也是这样的,目前比较流行的局域网有令牌环,以太网,WLAN等等,其中我们就重点解释一下令牌环和以太网。

首先是以太网

看到中间的那个圈了吧,我们如果把这个圈看成是以太网的话,那么不同的端系统,也就是主机接入以太网之后,就需要开始收发数据了吧?

那么在以太网中收发数据需要遵守几个原则:发数据的时候只能有一个发数据,收数据的时候可以有多个主机同时收。

如果多台主机同时发送数据,就会发送称为数据碰撞的情况,而对于所有发送数据的主机都需要进行碰撞检测和碰撞避免,那么在这种情况下,一个以太网就是一个碰撞域。

当数据发送到以太网之后,就需要通过MAC地址和IP地址来传递了,这个咱们后面谈,我们对于以太网有一个非常浅薄的认识就可以了。

接着是令牌环,对于令牌环我们是非常好理解的,因为我们是有锁的基础的,所以我们不妨把令牌看作是一个锁,谁有令牌谁就可以发数据,这就非常非常简单的理解了什么是令牌环。

然后是再认识协议了。

怎么说呢,对于协议来说,是整个网络世界的硬货,它是两台或多台主机之间的约定,是对于收发数据操作的一个统一吧。

不过我们之前已经有了对协议的第一层理解,现在我们将理解协议的第二层:

咱们就拿这个图举例吧,左边是Windows系统,右边是Linux系统,首先就会有人提问疑问:

两个不同的系统也能够通信吗?

首先,对于不同系统的网络协议栈来说,都是一样的,比如操作系统中的传输层和网络层的底层代码也差不到哪里去,也就意味着它们的API都是一样的,调用的接口都是一样的,都是C语言写的,数据格式也都是一样的,用的协议都是一样的,屏蔽操作系统其他的差异,就拿网络协议栈来说,如此多的共同点,难道不足以支撑它们通信吗?

那么问题来了,这和我们今天介绍的协议有什么关系吗?请注意我在上文提及到了数据格式都是一样的,那么你说,如果我从A主机定义了一个结构体,里面有int类型的三个变量,a,b,c,实例化了之后给B,你说B能读取到吗?

当然是可以的!

为什么可以?A给B一个数据,B不管是用拷贝的方式来接收还是用指针指向的方式来接收都可以,问题是为什么它可以,因为B中的数据格式是和A中的数据格式一样的,你想,如果B没有这个结构体,它能解析这个数据吗?它不能解析。

所以实际上,我们不用把协议想的太复杂了,它实际上就是双方都认识的一个结构化数据,就像咱们日常交流一样,我们都认识一个结构化数据叫做中文,所以我们可以无障碍交流。

到此,我们对于协议的第二层认识就出来了:协议是通信双方都认识的一个数据!


MAC/IP地址

介绍MAC和IP地址我们拿这张图作为例子,数据从应用层开始传输,传输的时候会填报文吧?报文里面有源IP和目的IP地址,这里的IP地址就是不同主机的在网络中的地址,你可以理解为现实中咱们的家庭地址。

那么IP地址的具体组成:

一、IPv4地址

IPv4地址由 32位二进制数 组成,通常以 点分十进制 格式表示(如 192.168.1.1)。

1. 基本结构

  • 4个十进制字段:每个字段占8位(1字节),范围为 0~255,用点分隔。
    示例:192.168.1.1 → 二进制为 11000000.10101000.00000001.00000001

2. 网络部分与主机部分

  • 网络号(Network ID):标识设备所属的网络。

  • 主机号(Host ID):标识网络中的具体设备。

  • 子网掩码:用于划分网络号和主机号。
    示例:255.255.255.0(二进制为 11111111.11111111.11111111.00000000)表示前24位是网络号,后8位是主机号。

  • 3. 分类(传统方式)

  • A类地址:首位为 0,网络号占8位(范围:1.0.0.0~126.255.255.255)。

  • B类地址:前两位为 10,网络号占16位(范围:128.0.0.0~191.255.255.255)。

  • 4. CIDR(无类域间路由)

  • 使用 斜线表示法(如 192.168.1.0/24),/24 表示前24位是网络前缀。

  • C类地址:前三位为 110,网络号占24位(范围:192.0.0.0~223.255.255.255)。

  • D类(组播)和 E类(保留)地址。

这上面的是DS生成的,我们暂时先了解一下,毕竟后面我们会详细介绍IP的。 

那么数据在传输的过程,会有一个动作,叫做路由,经过了路由就可以转接到正确的IP地址去,那么比如这里的SRC是192开头,DST是172开头,也就代表了这两个IP地址不在一个局域网,所以自然需要经过路由这个操作来让数据包走向正确的IP地址。

那么MAC地址又是怎么回事呢?对于MAC地址来说,它就是一个临时的,会随时变化的地址,比如路由这个操作有的时候要经过多次的转接,那么在转接的时候,你像A到B,B到C这里总会有一个中间地址C吧?

所以MAC地址就是临时的地址,它可以是路由器的地址,也可以是其他端设备的地址。

你要是觉得不好理解,你这样想,西天取经知道吧?唐僧的源IP是长安,目的IP是西天,MAC地址就是途中的车迟国啊,女儿国一类的。

而在封包的这个过程中,源IP和目的IP是一直不变的,其中的MAC地址就会随着封包的过程不断变化。

就像这样,以上是对于IP地址和MAC地址的解释。


Socket编程

到现在我们对于网络基础的纯概念部分已经了解了一些了,接下的理论基础就是为了编程方面操作了。

首先,我们要清楚,网络通信的本质是什么?

对于两个主机AB来说,它们真正要通信的不是两个主机之间进行通信,而是这台主机中的哪个进程要通信,比如我打开抖音,我是要通过抖音这个软件和字节跳动的服务器进行交互,而不是我这部手机要和字节跳动的机器交互。

所以网络通信的本质是什么呢?实际上是进程间通信!!

到这里同学是否会觉得和之前的系统编程有了联系?

好了,既然我们知道是进程间通信,下一个问题是,我们如何让信息精准无误的传输到我们想要的进程那里去?

在系统编程的时候我们了解到了进程有PID的概念,也就是在系统中唯一标识了系统的序列号,那么在网络中我们是否沿用PID还是再来一个网络方面的序列号呢?

首先,我们需要对方主机的IP这是肯定的,这是第一大点,需要对方的主机IP

其次,在网络中我们单独引了一个概念叫做端口号,这个端口号的作用呢就相当于系统中的PID,所以端口号的作用就是标识主机中某个进程的。

那么在网络世界中,我们有了IP地址和端口号,我们就可以找到网络中的唯一一个进程。此时我们通信的可靠性就增加了。

那么端口号一般是:

0-1023:知名端口号,HTTP,FTP,SSH等这些广为使用的应用层协议,他们的端口号都是固定的.

1024-65535:操作系统动态分配的端口号.客户端程序的端口号,就是由操作 系统从这个范围分配的.

比如HTTP的端口号都是80 HTTPS又是另一个。

所以Socket编程的Socket其实是等于IP + port

那么有人问了,为什么要用所谓的端口号而不是PID,PID多方便,还不用单独生成。

实则不然,如果我们继续沿用PID的话,那么系统和网络就会发生强耦合,这当然是不好的,强耦合带来的坏处不言而喻,一个错了导致另一个接着错,并且,对于端口号来说,不是所有的进程都需要端口号,一台机器上能进行通信的进程实际上没有那么多,所以即便不考虑解耦合的话,有些进程根本都不需要通信,我们还要它PID干嘛呢,不如我们单独拿一个概念出来专门为了通信。

其实主要就是为了解耦合

TCP/UDP

我们现在也可以简单理解一下传输层的两个大头,一个是TCP协议一个是UDP协议,对于TCP协议来说具有的特点是:有连接,面向字节流,可靠传输。对于UDP协议来说具有的特点是无连接,面向数据报,不可靠传输。

咱们一定要记住,上面的三个短句是它们的特点而不是所谓的优缺点。

这点我们在后面实现代码和学习它们本质的时候会了解到。

网络字节序

相信大家都知道大小端机器的差别,一个是低权重值低地址位,这是小端机器,高权重低地址位这是大端机器,那么如果大小端机器进行通信,假设发送的是同一份数据,但是因为大小端的差别导致它们得到的信息是相反的,这肯定是不行的,所以网络中引入了一个新的概念叫做网络字节序,实际上这个网络字节序就是大端的意思,代表上传到网络的数据必须是大端,接收数据也是。

至于怎么转换大小端,这咱们就不要关心了,函数已经帮我们实现好了。

那么这里至少涉及到的函数有:

uint32_t htonl(uint32_t hostlong);

uint32_t htons(uint16_t hostshort);

uint32_t ntohl(uint32_t hostlong);

uint32_t htohs(uint16_t hostshort);

其中对于函数h的意思代表host主机,l代表long,长整数,s代表short短整数,n代表network。

也就是这几个函数代表是从主机转网络还是从网络转主机。

好了,接下来我们了解了数据的传输方面,在了解一下IP地址常用的结构体,其中对于IPv4和IPv6都是用的sockaddr_in结构体,不过是参数方面不同而已,而对于sockaddr_un只能说我们一般都用不到,这是Unix域套接,怎么说呢,咱们不妨大手一挥,不用管它。

在网络世界中,因为Socket编程的API都是通用的,所以参数也是通用的,那么问题来了,这上面明明结构体不同啊,怎么会通过API呢?

实际上引入了sockaddr参数,当我们传入sockaddr_in和sockaddr_un的时候,需要强转一下就可以了。

并且你看这几个结构体的参数也是一摸一样的,你猜猜这是C语言的什么?

这不就是C语言的继承和多态吗!!!

好了,以上是理论基础的所有铺垫。


感谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75128.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka中的消息是如何存储的?

大家好,我是锋哥。今天分享关于【Kafka中的消息是如何存储的?】面试题。希望对大家有帮助; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Kafka 中,消息是通过 日志(Log) 的方式进行存储的。…

openEuler24.03 LTS下安装ZooKeeper集群

目录 前提条件 ZooKeeper集群规划 下载ZooKeeper 解压 配置环境变量 配置ZooKeeper 配置zoo.cfg 配置myid 分发到其他机器 修改其他机器myid 启动集群 关闭集群 集群启停脚本 前提条件 准备3台Linux机器,并安装好Java8 ZooKeeper集群规划 node2node3…

Python 实现机器学习小项目实战教程*

markdown 复制 Python 实现机器学习小项目实战教程 本教程将通过一个完整的机器学习项目案例,从数据预处理到模型部署,帮助初学者快速掌握机器学习核心流程。项目以经典的鸢尾花分类为例,使用 Scikit-learn 库实现。 1. 项目概述 目标 构…

rust学习笔记21-闭包

在 Rust 中,闭包(Closures) 是一种可以捕获其环境中的变量的匿名函数。它们非常灵活,既可以作为普通函数使用,也可以捕获和操作定义它们的作用域中的变量。闭包是 Rust 中处理短小逻辑代码块的强大工具,特别…

linux实现rsync+sersync实时数据备份

1.概述 rsync(Remote Sync) 是一个Unix/linux系统下的文件同步和传输工具 2.端口和运行模式 tcp/873 采用C/S模式(客户端/服务器模式) 3.特点 可以镜像保存整个目录和文件第一次全量备份(备份全部的文件),之后是增量备份(只备份变化的文件) 4. 数…

【第30节】MFC编程:ListCtrl控件和TreeCtrl控件

目录 引言 一、高级控件ListCtrl 二、高级控件TreeCtrl 三、Shell控件 四、CImageList 五、综合代码示例 引言 在MFC编程里,高级控件能大幅提升应用程序的交互性与功能性。接下来,咱们会详细讲讲ListCtrl和TreeCtrl这两个高级控件。不仅会介绍它们…

为什么 ThreadLocalMap 的 key 是弱引用 value是强引用

问题一:为什么 ThreadLocalMap 的 key 是弱引用? 【假设 Entry 的 key 是对 ThreadLocal 对象的强引用】:这个 Entry 又持有 ThreadLocal 对象和 value 对象的强引用。如果在其他地方都没有对这个 ThreadLocla 对象的引用了、然后在使用 Thr…

DeepSeek本地部署(linux)

一、下载并安装Ollama 1.下载Ollama Ollama官网:Ollama 点击"Download",会跳转至下载页面。 1.1在线下载安装 可复制此命令到Linux服务器进行在线下载,如下载速度过慢,可选择离线下载安装。 curl -fsSL https://ollama.com/install.sh | sh1.2离线下载安装 …

基于Halcon仿VM流程列表的执行效果

Halcon本身应用需要一定的门槛,但是也可以封装成类似VM简单易操作的样子 上期文章分享的是连线功能,本期分享数据传参 1,定义通用属性和方法 public class BaseModel {public HObject HInput { get; set; }//图像输入public HObject HOutpu…

打车APP订单系统逻辑梳理与实现

一、逻辑分析 打车 APP 订单系统是整个打车业务的核心,负责处理从乘客下单到行程结束的一系列流程,涉及乘客、司机和平台三方的交互。 乘客端 下单:乘客打开 APP,输入上车地点、目的地,选择车型等信息后提交订单。此时…

杂草YOLO系列数据集4000张

一份开源数据集——杂草YOLO数据集,该数据集适用于农业智能化、植物识别等计算机视觉应用场景。 数据集详情 ​训练集:3,664张高清标注图像​测试集:180张多样性场景样本​验证集:359张严格筛选数据 下载链接 杂草YOLO数据集分…

算法 | 河马优化算法原理,公式,应用,算法改进及研究综述,matlab代码

以下是关于河马优化算法(Hippopotamus Optimization Algorithm, HO)的完整综述,包含原理、公式、应用场景、改进方向及可直接运行的 Matlab 完整代码。一、算法原理 河马优化算法(HO)由Amiri等人于2024年提出,是受河马群体行为启发的元启发式算法,其核心基于以下三阶段行…

知识就是力量——HELLO GAME WORD!

你好!游戏世界! 简介环境配置前期准备好文章介绍创建头像小功能组件安装本地中文字库HSV颜色空间音频生成空白的音频 游戏UI开发加载动画注册登录界面UI界面第一版第二版 第一个游戏(贪吃蛇)第二个游戏(俄罗斯方块&…

Android Activity 的 launchMode 与 Task Stack 管理

Android 中的 android:launchMode 决定了 Activity 在启动时如何在任务栏中管理它的存在方式。下面我们来结合 Task Stack 管理详细解释。 1. android:launchMode 的四种模式 1.1 standard (标准模式, 默认) 启动方式:每次启动都会创建一个新实例并压入栏任务堆中…

2025选择手机之我见

自从开店之后,没当有手机召开发布会,我就得去大概看看,了解一下屏幕,充电之类的东西。毕竟跟我的生意息息相关,而且还得研究要不要上新,从我目前卖货的情况来看,折叠屏不是大众的选择&#xff0…

【区块链安全 | 第九篇】基于Heimdall设计的智能合约反编译项目

文章目录 背景目的安装1、安装 Rust2、克隆 heimdall-dec3、编译 heimdall-dec4、运行 heimdall-dec 使用说明1、访问 Web 界面2、输入合约信息3、查看反编译结果 实战演示1、解析普通合约2、解析代理合约 背景 在区块链安全研究中,智能合约的审计和分析至关重要。…

利用 PCI-Express 交换机实现面向未来的推理服务器

在数据中心系统的历史上,没有比被 Nvidia 选为其 AI 系统的组件供应商更高的赞誉了。 这就是为什么新兴的互连芯片制造商 Astera Labs 感到十分高兴,因为该公司正在 PCI-Express 交换机、PCI-Express 重定时器和 CXL 内存控制器方面与 Broadcom 和 Marv…

智能交通预警杆:守护道路安全的科技先锋

在城市化进程加速以及机动车保有量持续增长的背景下,道路交通安全与拥堵问题渐趋严峻。智能交通预警杆应时而生,其集成多种高科技功能,正逐步成为现代城市交通管理中至关重要的智能装备,对于提升交通效率、保障出行安全发挥着关键…

flink 基站与服务器长连接,每次连接和断开都会上报数据,统计过去一小时每个基站断开次数和时长

模拟生成数据 CREATE TABLE ods_station_log (base_station_id int, -- 基站IDevent_type int, -- 事件类型: connect/disconnectevent_time TIMESTAMP_LTZ(3), -- 事件时间WATERMARK FOR event_time AS event_time - INTERVAL 5 SECOND -- 允许5秒乱序 ) WITH …

自定义一些C语言的字符串函数

一、代码如下 (一)十六进制字符串转十进制整数 #include<stdio.h> // 把一个十六进制字符转成十进制整数 int hexToInt(char hexs[]){ int index; int k 0; for(k 0; ; k) { if(hexs[k] \0) { index k; break; …