Linux网络基础

手把手教你搭建硬件在回路(HIL)仿真系统:从Simulink建模到实时测试 本文详细介绍了如何从零开始搭建硬件在回路(HIL)仿真系统,涵盖Simulink建模、实时仿真、代码生成及调试等关键步骤。通过具体配置示例和优化技巧,帮助开发者解决复杂控制系统验证中的技术难题,提升半实物仿真的效率和可靠性。 阅读详情

网络基础


零、计算机网络背景

0.1 网络是怎么来的

计算机是人的工具,人要协同工作,注定了网络的产生是必然的。

回顾网络发展的三个阶段:

  • 独立模式: 计算机之间相互独立,数据交换只能靠软盘、U 盘这类物理介质
  • 网络互联: 多台计算机通过交换机和路由器连接在一起,完成数据共享
  • 局域网(LAN)→ 广域网(WAN): "局域网"和"广域网"只是相对概念——可以把有"中国特色"的广域网也看作一个比较大的局域网

0.2 什么是协议

"协议"是一种约定。

在这里插入图片描述

计算机之间的传输媒介是光信号和电信号,通过"频率"和"强弱"来表示 0 和 1 这样的信息。要想传递各种不同的信息,就需要约定好双方的数据格式。

思考:只要通信的两台主机约定好协议就可以了吗?

定好协议,但你用频率表示 01,我用强弱表示 01——就好比我用中国话,你用葡萄牙语。虽然大家可能都遵守"说话"这一基本通信规则,但语言不同,即使订好了协议,也无法正常通信。所以,完善的协议需要更多更细致的规定,并让所有参与方都遵守。

计算机生产厂商有很多,操作系统有很多,网络硬件设备还是有很多。如何让这些不同厂商生产的计算机能够相互顺畅通信?就需要有人站出来,约定一个共同的标准,大家都来遵守——这就是网络协议。

一、协议分层

在这里插入图片描述

两个主机通过网络通信,会产生什么问题?把这些问题逐个拆解:

  1. 相邻设备怎么传递数据? — 数据得在相邻设备之间传递,这是最底层的事:网卡怎么把信号发到网线上、怎么检测有新帧到达。
  2. 怎么找到目标主机? — 目标主机定位和路径选择问题。互联网上那么多主机,数据怎么知道该走哪条路才能到达目的地?
  3. 数据丢了怎么办? — 传输过程中数据出错、丢失、乱序怎么办?需要有人来保证可靠性。
  4. 数据到了之后做什么? — 前三个问题解决后,数据确实能从主机 A 跨网络到达主机 C。但到达不是目的——核心目的是处理这个数据,完成请求或应答。

这四个问题不是同一层面的问题——问题本身就能分层,所以解决方案自然也分了层。

为了解决这些问题,提出了 TCP/IP 协议,它本质是一种分层的解决方案:

问题对应层职责
问题 1 — 相邻设备传递网络接口层帧同步、冲突检测、差错校验
问题 2 — 定位与路由网络层IP 地址寻址 + 路由选择
问题 3 — 可靠性传输层TCP 保证可靠交付
问题 4 — 数据处理应用层应用程序间通信

1.1 为什么分层

协议分为硬件级别和软件级别,我们只考虑软件分层。

计算机的软件结构基本上是层状结构。比如虚拟文件系统,对磁盘、cache、内存等设备统一设置一个 struct file 结构——用一层软件抽象屏蔽底层差异。继承体系也是在类层面做软件分层。软件工程里有一句名言:任何问题都可以通过添加一层软件层来解决。

协议本质也是软件,在设计上为了更好的模块化、解耦合,也被设计为层状结构。分层从软件工程角度实现了低耦合——每一层只关心自己该做的事,修改一层不影响其他层。

1.2 OSI 七层模型

在这里插入图片描述

OSI(Open System Interconnection,开放系统互连)七层网络模型称为开放式系统互联参考模型,是一个逻辑上的定义和规范。它把网络从逻辑上分为了 7 层,每一层都有对应的物理设备(如路由器、交换机)。

它的最大优点是将服务、接口和协议这三个概念明确地区分开来,概念清楚,理论也比较完整。通过七个层次化的结构模型,使不同系统、不同网络之间能实现可靠通讯。

但它既复杂又不实用——在工程实践中,我们按照 TCP/IP 模型来讲解。

为什么 OSI 七层最终落地是五层?

从网络角度看,OSI 的七层协议模型其实非常完善。但在实际操作过程中,会话层和表示层是不可能接入到操作系统中的——它们的功能被合并到了应用层中。所以工程实践中最终落地的是五层协议。(这句话的真正含义,学完网络自然会理解。)

1.3 TCP/IP 五层(或四层)模型

TCP/IP 是一组协议的代名词,它还包括许多协议,组成了 TCP/IP 协议簇。

TCP/IP 通讯协议采用了 5 层的层级结构,每一层都调用它的下一层所提供的网络来完成自己的需求:

  • 物理层: 负责光/电信号的传递方式。比如现在以太网通用的网线(双绞线)、早期以太网采用的同轴电缆(现在主要用于有线电视)、光纤,现在的 WiFi 无线网使用电磁波等,都属于物理层的概念。物理层的能力决定了最大传输速率、传输距离、抗干扰性等。集线器(Hub)工作在物理层。
  • 数据链路层: 负责设备之间的数据帧的传送和识别。例如网卡设备的驱动、帧同步(从网线上检测到什么信号算作新帧的开始)、冲突检测(如果检测到冲突就自动重发)、数据差错校验等工作。有以太网、令牌环网、无线 LAN 等标准。交换机(Switch)工作在数据链路层。
  • 网络层: 负责地址管理和路由选择。例如在 IP 协议中,通过 IP 地址来标识一台主机,并通过路由表的方式规划出两台主机之间的数据传输的线路(路由)。路由器(Router)工作在网络层。
  • 传输层: 负责两台主机之间的数据传输。如传输控制协议(TCP),能够确保数据可靠的从源主机发送到目标主机。
  • 应用层: 负责应用程序间沟通,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等。我们的网络编程主要就是针对应用层。

在这里插入图片描述

物理层我们考虑得比较少,只考虑软件相关的内容——因此很多时候我们直接称为 TCP/IP 四层模型。

1.4 各层在设备中的实现

一般而言:

  • 主机: 操作系统内核实现了从传输层到物理层的内容
  • 路由器: 实现了从网络层到物理层
  • 交换机: 实现了从数据链路层到物理层
  • 集线器: 只实现了物理层

但并不绝对——很多交换机也实现了网络层的转发,很多路由器也实现了部分传输层的内容(比如端口转发)。


二、再识协议——从本质理解

上一章我们知道了协议分层的框架。但"协议"到底是什么?它和操作系统又是什么关系?这一章我们从本质出发,把这个问题讲透。

2.1 什么是协议——从数据结构视角

先来回答第一个问题。站在数据结构的视角,一个朴素的理解是:

协议就是通信双方都认识的结构化的数据类型。

仔细看看下面这张图:

在这里插入图片描述

想象这样一个场景:主机 A 定义了一个结构体 struct protocol,里面放着 a=10, b=20, c=30,然后把这个结构体的二进制数据发给主机 B。主机 B 能识别并准确提取出这三个值吗?

答案是肯定的——因为双方都有同样的结构体类型。用同样的代码实现协议、用同样的自定义数据类型,天然就具有"共识",能识别对方发来的数据。这不就是约定吗?

从内核角度来看:假设传输层定义了一个结构体,主机 A 把这个结构体对象发送给主机 B 的传输层。由于协议必须相同,接收方收到数据后可以直接提取结构体成员——双方用约定结构体的方式进行传输。协议的本质,就是结构体。

更进一步,这个道理在生活中比比皆是。网购时,快递单就是一种"协议":发件人和收件人都认识快递单的格式(收件人姓名、地址、电话……),双方不需要额外沟通就能完成数据的传递。网络协议的道理完全一样。

所谓协议,就是通信双方都认识的结构化的数据类型。

因为协议栈是分层的,所以每一层双方都有对应的协议——同层之间,互相可以识别对方的协议。

2.2 为什么要有 TCP/IP 协议

搞清楚了协议的本质,再来追问:为什么需要 TCP/IP 这一整套协议?即便是单机,你的计算机内部其实也存在协议。比如:其他设备和内存通信有内存协议,其他设备和磁盘通信有磁盘协议(如 SATA、IDE、SCSI 等)。只不过我们感知不到——这些协议都在本地主机的硬件中,通信的成本低、问题少。

网络通信最大的特点就是主机之间变远了。任何通信特征的变化,一定会带来新的问题;有问题就得解决问题。所以,TCP/IP 协议存在的本质原因就是:通信主机距离变远了。

2.3 TCP/IP 协议与操作系统的关系

先聊聊操作系统和协议的关系——TCP/IP 协议在宏观上是怎么实现的?

在这里插入图片描述

操作系统都是用 C 和部分汇编写成的,协议栈的部分直接被内置在内核中——也就是说,协议栈本身也是用 C 写的。由于大家都要遵守 TCP/IP 协议,不同操作系统的网络协议栈代码其实都差不多。其中,传输层和网络层被编写在内核中,因为协议本身必须高效运行在操作系统底层。

协议栈的代码,位于操作系统的内核中,一般用 C/C++ 实现。当你在用户态调用 socket()、bind() 这些 API 时,实际上最终会触发内核中的协议栈代码去执行封装、路由、发送等工作。

后面我们编写 socket 程序时,写的虽然是应用层代码,但底层其实依赖了一整套内核协议栈。


三、网络传输基本流程

有了协议分层的框架,接下来我们具体看一次网络传输中,数据是如何从一台主机到达另一台主机的。

3.1 局域网通信原理

网络通信其实是网络协议栈进行通信。首先回答核心问题:两台主机在同一个局域网内,是可以直接通信的。

下面谈局域网通信的原理——类似于上课:每一次老师想和谁通话,就叫谁的名字,但全班都能听到。局域网内的每台主机也是如此。

每台主机在局域网上,有 MAC 地址作为唯一的标识来保证主机的唯一性。它是一张网卡一个 MAC 地址,硬件固定。

具体来看一个通信过程:主机 A 向主机 E 发送"你好"。报头结构体中 src 为 MacA,dst 为 MacE,有效载荷 data 为"你好"。局域网内所有主机 B、C、D、E 都能看到这个报文——除了 E,其他主机发现 dst 的 MAC 地址不是自己,就直接丢弃。直到主机 E 发现是发给自己的,返回信息。这就是以太网通信的基本过程。

在这里插入图片描述

局域网和以太网是什么关系?

以太网是局域网的一种具体实现,就像 bash 是 shell 的一种具体实现一样。除了以太网,还有令牌环网等其他局域网通信标准。

在以太网中:

  • 任何时刻,只允许一台机器向网络中发送数据
  • 如果多台同时发送,会发生数据干扰——称为数据碰撞
  • 所有发送数据的主机要进行碰撞检测和碰撞避免
  • 没有交换机的情况下,一个以太网就是一个碰撞域
  • 局域网通信的本质,就是基于碰撞检测和碰撞避免的不断重试

局域网中如果主机越来越多,发生碰撞的概率就会越来越大。

换个视角:从系统层面看以太网。 以太网就是共享资源——碰撞检测和碰撞避免,本质上是让共享资源在同一时间只能被同一个主机使用。可以把它看成临界资源,要保证发送数据的原子性。用操作系统的视角看待网络,很多概念就能打通。

主机对收到的报文,通过目标 MAC 地址来判定是否是发给自己的。

3.2 认识 MAC 地址

MAC 地址用来识别数据链路层中相连的节点:

  • 长度:48 比特位,即 6 个字节,一般用 16 进制数字加冒号的形式表示(例如:08:00:27:03:fb:19)
  • 在网卡出厂时就确定了,不能修改,通常是唯一的(虚拟机中的 MAC 地址不是真实的 MAC 地址,可能会冲突;也有些网卡支持用户配置 MAC 地址)
  • Linux 下使用 ifconfig 查看 MAC 地址(ether 后面的字段);Windows 下执行 ipconfig /all

后面我们详细讨论数据链路层时,会谈 MAC 帧协议,此处先有一个基本认识即可。

3.3 封装与解包

现在思考一个更深的问题:主机 A 为什么要给主机 E 发消息?是用户驱动的。所以真实数据通信中,用户在最上层,但数据必须由硬件发出、由硬件接收——这就注定了数据必须贯穿网络协议栈。我们要把各层的报头依次加到传输内容中,每一层协议都要添加自己的报头。

在这里插入图片描述

其中每层都有协议,所以进行上述传输流程时,必然要进行封装和解包:

在这里插入图片描述

下面我们明确几个核心概念:

在这里插入图片描述

报文 = 报头 + 有效载荷

  • 报头(header): 对应协议层的结构体字段,包含了"首部有多长"、“有效载荷有多长”、"上层协议是什么"等信息
  • 有效载荷(payload): 每层自己的协议报头之外的就是有效载荷——除去报头,剩下的数据

不同协议层对完整报文有不同的叫法:

层报文名称
传输层段(segment)
网络层数据报(datagram)
链路层帧(frame)

封装的本质——从内存视角看

在谈怎么解包之前,先理解封装的本质。前面说过,所谓协议本质是一个结构体类型,报头就是结构体变量。封装的具体过程如下:

为了保存数据,内存中有缓冲区。用户发送"你好",数据先放入缓冲区;随后进入下一层,计算出该层报头需要的大小,指针向前偏移,腾出报头空间——再向下一层,以此类推。封装报头的本质,其实就是在报文头部,拷贝结构体变量。

在这里插入图片描述

解包——两件必须做的事

当底层协议收到报文,不管是什么协议,都要做两件事情:

  1. 分离报头和有效载荷(解包) ——如何处理?未来我们会遇到固定长度的报头和变长的报头,处理方式不同
  2. 将有效载荷向上交付给正确的协议(分用) ——报头里就有内容用于区分协议类别,封装的时候已经把相关信息写入报头了

在这里插入图片描述

每层协议都要做到这两件事——第一件事是解包,第二件事是分用。

如果从内存视角来看,封装和解包的过程就是入栈和出栈的过程——所以整套协议软件被称为协议栈。

3.4 数据包封装和分用

在网络传输的过程中,数据不是直接发送给对方的,而是先自上向下将数据交付给下层协议,最后由底层物理设备发送;到达对方后,再由底层自底向上逐层交付给上层协议。

从今天开始,学习任何协议,都要先宏观上建立两个核心认识:

  1. 这个协议是如何解包的? ——只有明确了解包方式,封装也就自然能理解
  2. 这个协议是如何将有效载荷交付给上层协议的? ——每一层的存在意义,就是为上层服务

四、跨网络传输——IP 地址

第三章讨论了局域网内的通信,但互联网上的主机绝大多数不在同一个局域网里。跨网络通信,相比局域网多了个关键角色——路由器。同时,跨网络通信还需要一个全局的寻址机制——这就是 IP 地址。

在网络传输中,必须解决主机定位和路由选择两个问题,此处引入全新的地址类型:IP 地址。IP 地址侧重的是:标识公网中唯一的一台主机,解决"主机在哪、数据走哪条路"的问题。

你可能会问:不是每台主机都有 MAC 地址吗?MAC 地址就可以标识局域网内的唯一性,那为什么需要两个地址?

答案在于场景不同。下面这张图展示了主机 A 给主机 B 跨网络发送"你好"的完整过程:

在这里插入图片描述

消息从主机 A 出发:先向下交付,添加应用层报头 → 添加 TCP 报头 → 添加 IP 层报头 → 添加 MAC 帧报头。此时判断目标主机不在局域网内,于是分离分用后发送给路由器。路由器确认目标地址后(路由器工作在网络层,不能直接把数据报交给同层),只能向下封装交给令牌环网,随后再一步一步解包分用,最终到达主机 B。

4.1 认识 IP 地址

IP 协议有两个版本:IPv4 和 IPv6。我们整个课程凡是提到 IP 协议,没有特殊说明的都默认指 IPv4。

  • IPv4 地址是一个 4 字节,32 位的整数
  • 通常使用**“点分十进制”**的字符串表示,例如 192.168.0.1——用点分割的每一个数字表示一个字节,范围是 0~255

跨网段的主机之间传输数据,需要经过一个或多个路由器。数据在每一跳中重新封装,但目的 IP 地址始终不变——它指引着数据前进的方向。

4.2 IP 地址 vs MAC 地址

现在来回答前面的问题:为什么有了 MAC 还要 IP?

  • IP 地址在整个路由过程中,一直不变(目前只能这样说明,后面会修正)。IP 地址表示的是"从哪里来,到哪里去"——是长远目标。
  • MAC 地址一直在变。MAC 地址表示的是"上一站从哪里来,下一站去哪里"——是下一阶段目标。
IP 地址MAC 地址
路由过程一直不变(长远目标)一直在变(下一阶段目标)
作用路径选择的重要依据局域网转发的重要依据

目的 IP 是一种长远目标,MAC 是下一阶段目标。目的 IP 决定走哪条路,MAC 决定这一步交给谁。

下面带上 IP 地址,再来看主机 A 向主机 B 发消息的完整过程。假设主机 A 的 IP 是 192.168.2.2,目标主机 B 的 IP 是 172.168.2.2。局域网内部还有其他主机 192.168.2.3、192.168.2.4。在网络层,主机 A 不知道 172.168.2.2 是谁,但它能判断目标不在本局域网内——于是只能把报文交给路由器。

在这里插入图片描述

下面结合封装与解包,来看路由器如何解包后重新封装:

在这里插入图片描述

主机 A 上层交付下来,层层封装。在网络层封装时发现目的不在同一局域网,因此 MAC 帧头封装为 macLeft(指向路由器左网卡)。数据包发出后,局域网内其他主机看到 dst 不是自己的 MAC,直接丢弃。路由器收到数据包后,把报头和有效载荷分离,解包分用后,将有效载荷交给路由器的网络层。路由器网络层查看目的 IP 172.168.2.2,匹配路由表,发现该网段从右侧网卡出去——于是在右侧链路层封装新的以太网帧头 macRight,由路由器右网卡把新帧发送到右侧局域网。主机 B 网卡收到路由器转发过来的完整 MAC 帧,逐层向上解包。

4.3 IP 网络层的意义

为什么需要 IP?——从底层差异看网络层的价值

在网络层,收发的是同一种报文(IP 数据报)。但网络层往下,数据链路层可能是以太网报头、令牌环网报头、无线网报头……局域网标准并不统一,标准不同,实现方式也不同。把涉及硬件的所有局域网全部统一是不现实的。于是就出现了 IP 协议——网络层之上(包括网络层),所有协议标准统一(IP 网络);网络层往下,标准不统一。

IP 网络层统一互联网通信标准,就和虚拟地址空间通过页表映射到物理空间一样——上层看到统一抽象,底层各自实现。

网络通信的宏观流程,如图:

在这里插入图片描述


五、Socket 编程预备

掌握了 IP 地址之后,我们离编写网络程序还差最后一环:数据到达主机后,怎么交给具体的进程? 这就是传输层的核心问题,也是 socket 编程的起点。

5.1 源 IP 和目的 IP

IP 在网络中用来标识主机的唯一性。但想一想:数据传输到主机就是目的吗?

不是的。数据是给人用的——聊天是人在聊天,下载是人在下载,浏览网页是人在浏览。而人是怎么看到这些信息的?通过启动的 QQ、迅雷、浏览器……它们都是进程。换句话说,进程是人在系统中的代表——只要把数据交给进程,人就相当于拿到了数据。

所以:数据传输到主机不是目的,而是手段。到达主机内部,再交给主机内的进程,才是真正的目的。

在这里插入图片描述

但系统中同时会存在非常多的进程。当数据到达目标主机之后,怎么准确地转发给目标进程?这就是下一个问题:如何在网络背景下标识主机内进程的唯一性。

5.2 端口号(port)

端口号是传输层协议的内容:

  • 是一个 2 字节 16 位的整数
  • 用来标识一个进程,告诉操作系统"当前这个数据要交给哪一个进程来处理"
  • IP 地址 + 端口号 = 能够标识网络上某一台主机的某一个进程
  • 一个端口号只能被一个进程占用,但一个进程可以绑定多个端口号

在这里插入图片描述

拿上图来说,两个主机上都有 QQ 进程。主机 A 的 QQ 进程端口号绑定为 8888,主机 B 的绑定为 9999。报文就像下面这样:

src_port: 8888    dst_port: 9999
src_ip: 192.168.2.3
dst_ip: 192.168.2.4
data: ...

这个报文一定能转发给主机 B——但发送到主机 B 不是目的,只是手段。解包后拿到 9999,才能发送到对应的 QQ 进程。

所以,网络通信的本质是进程间通信。从冯·诺依曼体系视角来看,进程发送数据到网卡、进程从网卡接收数据——这就是 I/O 操作。从 Linux 一切皆文件的视角,网络也是文件,读写网络就是 I/O。

端口号范围划分:

范围类型说明
0 ~ 1023知名端口号HTTP、FTP、SSH 等广为使用的应用层协议,端口是固定的
1024 ~ 65535动态端口操作系统动态分配,客户端程序从这个范围获取端口

端口号 vs 进程 PID:

我们在系统编程中学习了 PID 表示唯一一个进程,端口号也能唯一标识一个进程,那为什么不直接用 PID?

  • 理由一:解耦。 PID 属于系统概念,从技术角度确实能实现;但端口号属于网络概念。如果都用一个,系统只要修改就可能影响网络——做好系统和网络的解耦才是正确的设计。
  • 理由二:范围区分。 PID 每个进程都要有,但并不是所有进程都需要进行网络通信。没有端口号的进程就不需要网络通信,端口号是网络通信的强标识。

打个比方:就像 10086——你可以打 10086 找中国移动客服,但你不需要知道接电话的是工号 9527 还是 9528。PID 是系统内部的概念,端口号是网络对外暴露的概念,二者各司其职。

IP vs Port 的关系:

IP 地址标识主机,一个主机上可能有多个需要网络通信的进程——所以一个 IP 可以对应多个 port。

扩展——OS 是怎么把数据交给特定进程的?

  1. 怎么找到进程? OS 内部存在一个 hash 表用于绑定端口号和进程。进程在绑定端口时,会把自己的 PCB 链入这个 hash 表。当数据到达时,通过端口号查 hash 表就能找到对应进程。

  2. 找到进程后,怎么把网络数据交给它? 网络报文会源源不断地传输到网络层,可能存在积压。大量报文需要管理——OS 必然有内核数据结构指向缓冲区,随后对这些数据结构进行管理。在 Linux 一切皆文件的体系下,网卡是文件,被进程打开后,进程内部有属于自己的 fd,struct file 指向文件缓冲区。进程找到了,通过 fd 就能找到 file 结构体,也就找到了缓冲区,拿到了数据报。(这种说法不是特别准确,后面会更正。)

5.3 理解 socket

综上:

  • IP 地址用来标识互联网中唯一的一台主机
  • port 用来标识该主机上唯一的一个网络进程
  • IP + Port 就能表示互联网中唯一的一个进程

网络通信的本质,就是两个互联网进程代表人来进行通信。四元组 {srcIp, srcPort, dstIp, dstPort} 就能标识互联网中唯二的两个进程。

网络通信的本质,也是进程间通信。

我们把 ip + port 叫做套接字(socket)。多个 socket 组成连接,后面网络编程的核心就是对 socket 的操作。

网络中不同进程之间是有独立性的,要让它们看到同一个共享资源——这个共享资源就叫网络。所以,网络通信本质也就是进程通信。

5.4 TCP 与 UDP(初步认识)

传输层属于内核。要进行网络通信,操作系统不可能直接把内核暴露给用户,必然要提供系统调用——TCP 和 UDP 就是为此而存在的。

在网络通信过程中,操作系统其实不知道用户未来要走什么样的通信流程(就像程序替换时 OS 不知道具体要传什么参数一样),所以传输层要提供多种协议,让用户根据场景自由选择。两个最核心的传输层协议:

TCPUDP
全称Transmission Control ProtocolUser Datagram Protocol
连接有连接无连接
可靠性可靠传输不可靠传输
面向字节流数据报

有连接 vs 无连接: 打电话就像是有连接的——先拨号、对方接听、然后通话;发微信或邮件就像是无连接的——消息直接发出,不确认对方是否在线。

可靠 vs 不可靠: TCP 和 UDP 的区别在于对数据丢失是否处理。但不要把"不可靠"当成缺点——要当成特点。可靠意味着要做更多的工作(重传、确认、排序),不可靠意味着更快、开销更小。选择哪个,取决于场景:要数据完整性就用 TCP,要低延迟就用 UDP。

此处先有一个直观认识,后面还会详细讨论 TCP 的诸多细节。

5.5 网络字节序

什么是大端和小端?

内存中有低地址和高地址。假设一个数据 int a = 0x1234abcd,按字节存储:12 是高位,cd 是低位。

  • 小端(little-endian):低位写低地址 —— 记法:“小小小”(小端 = 低位 → 低地址)
  • 大端(big-endian):低位写高地址 —— 反之

为什么会存在大小端? 就跟为什么会存在不同的局域网标准一样——当时各实验室有自己的实现方案,各自为政,历史原因形成了两种字节序。

在网络中,不管你是什么端,规定是:先发出的数据是低地址,后发出的数据是高地址。于是:

  • 小端机器会按字节序 cd ab 34 11 发出
  • 大端机器会按字节序 12 34 ab cd 发出

在这里插入图片描述

接收端也按同样方式接收。但如果两端大小端不一致,处理数据时就会把数据搞反。怎么解决?

TCP/IP 协议规定:网络中传递的数据必须是大端字节序。 不管当前主机是大端机还是小端机,都必须按这个规定来——小端机需要先将数据转成大端再发送,大端机可以直接发送。

系统提供了一批转换接口:

函数含义
htonlhost to network long,32 位(如 IP 地址)
htonshost to network short,16 位(如端口号)
ntohlnetwork to host long,32 位
ntohsnetwork to host short,16 位
  • 如果主机是小端:这些函数做相应的大小端转换然后返回
  • 如果主机是大端:这些函数不做转换,将参数原封不动地返回

大部分时候我们不需要关心大小端问题——读写已经自动帮我们转化好了。个别情况需要我们手动转换,比如填充端口号和 IP 地址时。

📌 网络规定:所有发送到网络上的数据,都必须是大端的!

5.6 socket 编程接口

socket 常用 API(<sys/socket.h>):

// 创建 socket 文件描述符(TCP/UDP,客户端 + 服务器)
int socket(int domain, int type, int protocol);

// 绑定端口号(TCP/UDP,服务器)
int bind(int socket, const struct sockaddr *address, socklen_t address_len);

// 开始监听 socket(TCP,服务器)
int listen(int socket, int backlog);

// 接收请求(TCP,服务器)
int accept(int socket, struct sockaddr* address, socklen_t* address_len);

// 建立连接(TCP,客户端)
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

5.7 sockaddr 结构

看一下前面列出的 socket API:bind()、accept()、connect()……很多接口的参数里都有一个 struct sockaddr* address。这个结构体是什么?为什么这么设计?

三种通信场景,一套接口

socket 的设计者要支持多种通信场景:

  • INET socket: 网络通信,需要 IP 地址 + 端口号
  • UNIX socket: 本地通信(特别像命名管道),需要传递路径名
  • raw socket: 原始套接字,用来设计网络工具

作为设计者,难道要为三种场景设计三类不同的系统调用吗?那样用户的使用成本会大大增加。

解决方案:再加一层软件层。

还记得前面说的吗——任何问题都可以通过添加一层软件层来解决。这里正是这个思想的应用:统一函数接口,统一传递参数。接口统一容易,但参数不一样怎么办?

  • 网络通信需要传递 IP 和端口号 → 封装成 sockaddr_in 结构体
  • 域间通信需要传递路径名 → 封装成 sockaddr_un 结构体

再设计一个通用结构体 sockaddr 作为"基类",所有 API 的参数都是 sockaddr* 类型。函数内部根据地址类型字段(AF_INET / AF_INET6 / AF_UNIX)判断,进而强转成对应的子类结构体。

这不就是面向对象里的多态吗?sockaddr 是基类,sockaddr_in 和 sockaddr_un 是子类,函数接收基类指针,内部按需向下转型。

在这里插入图片描述

具体来说:

  • IPv4 和 IPv6 的地址格式定义在 <netinet/in.h> 中。IPv4 地址用 sockaddr_in 结构体表示,包含:16 位地址类型 + 16 位端口号 + 32 位 IP 地址
  • 地址类型分别定义为常量 AF_INET(IPv4)/ AF_INET6(IPv6)
  • socket API 统一使用 struct sockaddr* 类型,使用时需要强制转化成 sockaddr_in

in_addr 结构用来表示一个 IPv4 的 IP 地址,本质就是一个 32 位的整数。


android 蓝牙通讯demo android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。 立即下载

相关推荐

Pinocchio 安装教程|机器人学的必备库

安装pinocchio,不要安装pip3 install pinocchio!

darcsdn 1662

【Linux】网络基础知识

实际的网络通信中,必然有一端主机的地址和端口是固定的,同时是让所有人都知道的,这端称为服务器端(为用户提供服务的一端),网络应用提供商,都会搭建自己的服务器,向外发布的客户端程序中都封装了自己的服务器地址信息在里面。IPv6,uint8_t ip[16],数据非常的大,但是并不向前兼容IPv4,即若直接使用IPv6进行通信,那么原来基于IPv4的设备程序都用不了,所以推广很慢,当前主要的网络通信还是基于IPv4的通信。其端口只有两个,即输入端和输出端,将输入的信号进行放大再发送出去。

m0_69597277的博客 2404

量化投资从0开始系列 ---- 15. 郑商所日统计数据

前面已经提取了其它期货交易所的数据,最后还剩下郑商所。相比而言,郑商所的数据获取比其它几个交易所更麻烦一点。因为郑商所的系统接口有两个,在2015年11月11日前后发生了切换,这个日期之前是老系统的api接口,这个日期之后是一个新的api接口。 具体的地址在哪里,还是依靠在浏览器中按F12来确定,最后发现的地址是: if trade_date > '20151111': czce_url = f'http://www.czce.com.cn/cn/DFSS

kengxie的博客 2112

网络入门基础

文章目录计算机网络背景网络发展认识“协议”网络协议初始协议分层OSI七层模型TCP/IP五层(或四层)模型网络传输基本流程网络传输流程图数据包封装和分用网络中的地址管理认识IP地址认识MAC地址 计算机网络背景 网络发展 认识“协议” 网络协议初始 协议分层 OSI七层模型 TCP/IP五层(或四层)模型 网络传输基本流程 网络传输流程图 数据包封装和分用 网络中的地址管理 认识IP地址 认识MAC地址 ...

2021dragon的博客 1万+

君正T31x metartc集成测试

metartc为国内杨大侠部分开源的一款用于嵌入式领域webrtc库,它与谷歌官方webrtc相比,编译到君正平台的可执行文件仅有5M即可实现webrtc的通信。1. 目前实现的是基于开源版v5.0-b0版本做的简单修改,官方的好几个版本都多少缺点东西,我这里给整理了一下。目前是局域网连接的webrtc,后续尝试走stun和turn试一下NAT穿越的效果。

fsmpeg的博客 3158

基于开源项目构建 CFS(网络靶场实战演练)平台

摘要:构建CFS网络靶场可使用多个开源组件组合,包括EVE-NG/GNS3或ContainerLab构建网络环境,Kasm提供工作空间,CALDERA+Atomic Red Team实现攻击模拟,DetectionLab建立防御环境,Malcolm/Arkime进行流量监控,CyRIS提供编排框架,Vulhub/DVWA创建漏洞靶标。关键在于通过API深度集成各组件,同时需注重安全隔离、资源规划及维护成本。建议开发统一管理平台,结合Ansible/Terraform实现自动化部署,打造定制化实战演练环境。(

深山技术宅的博客 1846

【Linux 网络(一)】初识网络,理解TCP/IP五层模型

本篇文章将会介绍网络产生的背景、OSI网络7层、已经网络传递过程中报文解包封装的宏观结构

Zhenyu_Coder的博客 1822

华为OD机试 - 小火车最多人时所在园区站点(Java 2024 E卷 100分)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、发现新题目,随时更新,全天优快云在线答疑。

学Java,找哪吒 996

Linux:计算机网络基础

网络协议;局域网、以太网;OSI、TCP/IP结构模型;数据包封装、分用;交换机、路由器;IP地址和MAC地址.....

kimsaul的白给岁月 1419

下采样优化实战:用ADown显著提升YOLOv11的多尺度特征保持能力

ADown 以“可编程梯度信息+多分支特征融合”打破了传统下采样的性能壁垒,为 YOLOv11 带来了多尺度特征的精准传递能力。从原理到代码集成,本教程已为你铺就了一条“小目标检测精度跃升”的实战路径。现在就动手尝试吧——当你看到模型对极小目标也能精准识别,且特征图细节完整时,你会明白这份技术探索的价值。我很乐意在你实践过程中帮你解决任何问题,让我们一起推动目标检测在下采样领域的边界。

FJN110的博客 421

【QT开发教程】使用Qt进行NFC编程

近场通信(NFC,Near Field Communication)技术广泛应用于现代设备中,例如智能手机、支付终端和门禁系统。Qt提供了一套完整的NFC模块,使开发者可以轻松地在应用程序中实现NFC功能。本文将介绍如何在Qt中进行NFC编程,包括基本概念、使用方法以及一些实际的示例。

科技改变人类,技术成就未来 1469

Linux 网络基础篇

从今天开始开始更新Linux的网络基础,希望大家多多关注,指出错误,我的Linux系统管理已经更新完成,有需要的可以去看看,链接: 链接: 从零开始学习Linux. Linux 网络基础篇第一章 计算机基础第一节 进制转换第二章 网络基础第一节 互联网概述第二节 互联网接入方法第三章 网络通信协议第一节 OSI七层模型和TCP四层模型 第一章 计算机基础 第一节 进制转换 十进制数:逢是进一 1 2 3 4 5 6 7 8 9 10 二进制数:逢二进一 0 1 10 11 100 101 110 1

yy150122的博客 1万+

通信原理 | 通俗理解 | 因子图、消息传递以及它们之间的关系

在算法迭代过程中,通过反复更新这些消息,直到收敛,最终可以得到每个变量的边缘概率分布或最有可能的整体状态。算法通过因子图中的节点反复交换消息,直到找到最优解或所有消息稳定下来,从而解决了比如聚会日期这样的优化问题。在实际应用中,这种方法可以用来解决更复杂的问题,比如图像识别、语音识别和机器学习中的其他问题。,特别是在处理概率模型和执行概率推断时,因子图提供了一个强大的工具。(比如朋友的空闲时间和地点的可用性),并且你希望尽可能让所有人满意。在真正的因子图和消息传递算法中,这个过程被数学化和形式化。

若北辰 1196

Linux之网络基础概念

Linux之网络基础概念

2302_81120572的博客 1301

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【Linux】网络基础

【Linux】网络基础,一文带你入门网络

tan_run的博客 8020

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

CTF 赛前指导之 Linux 基础与网络基础

在 CTF(夺旗赛)的世界里,Linux 基础和网络基础的掌握对于参赛选手来说至关重要。CTF 比赛涉及到各种各样的挑战,其中很多环节都需要选手能够熟练运用 Linux 系统进行操作,同时对网络相关知识有深入理解,以便更好地分析和解决题目,找到隐藏的 flag 值。

m0_57836225的博客 1102

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Linux网络基础知识全面总结

本文全面介绍了Linux网络基础知识及相关配置、工具、远程连接与管理、防火墙与安全性、网络服务与配置、虚拟网络与容器技术以及网络故障排除和调优等内容。通过阅读本文,你将对Linux网络有更深入的理解,并能够应用于实际的网络环境中。

qq_41308872的博客 1万+

Linux 网络基础学习

Linux 网络基础知识 网络的基础知识包括: TCP/IP , Network IP, Netmask IP , Broadcast IP,Gateway, DNS IP等等

daiyuntao841226的专栏 2082

linux网络基础

本文资料内容来自的视频内容整理。

2302_79253478的博客 853
上一篇: 线程同步与互斥
下一篇: socket编程UDP
oMMMen
博客等级 码龄7年 234粉丝 81原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值