【Linux网络】计算机网络入门:Socket编程预备,从字节序共识到 Socket 地址结构的“伪多态”设计

🎬 个人主页艾莉丝努力练剑
专栏传送门 :《C语言》《数据结构与算法》《C/C++干货分享&学习过程记录
Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享

⭐️为天地立心,为生民立命,为往圣继绝学,为万世开太平


🎬 艾莉丝的简介:


文章目录

  • 前言
  • [1 ~> 通信的本质 ------ 跨越主机的"进程对话"](#1 ~> 通信的本质 —— 跨越主机的“进程对话”)
  • [2 ~> 传输层的抉择------TCP 与 UDP 的性格标签](#2 ~> 传输层的抉择——TCP 与 UDP 的性格标签)
    • [2.1 UDP (用户数据报协议):](#2.1 UDP (用户数据报协议):)
    • [2.2 TCP (传输控制协议):](#2.2 TCP (传输控制协议):)
    • [2.3 思维导图](#2.3 思维导图)
  • [3 ~> 网络字节序:关于"共识"](#3 ~> 网络字节序:关于“共识”)
    • [3.1 总结大小端字节序问题](#3.1 总结大小端字节序问题)
    • [3.2 为什么不能在报文中带上端标?](#3.2 为什么不能在报文中带上端标?)
    • [3.3 核心价值:建立共识](#3.3 核心价值:建立共识)
    • [3.4 为什么选择大端?(大端的微弱优势)](#3.4 为什么选择大端?(大端的微弱优势))
  • [4 ~> socket常见API](#4 ~> socket常见API)
  • [5 ~> sockaddr 接口的"多态"实现](#5 ~> sockaddr 接口的“多态”实现)
    • [5.1 sockaddr 结构](#5.1 sockaddr 结构)
    • [5.2 结构体家族](#5.2 结构体家族)
    • [5.3 万能基类](#5.3 万能基类)
  • [6 ~> 为什么要有 Socket?](#6 ~> 为什么要有 Socket?)
  • 结尾


前言

在网络通信中,底层细节往往决定了系统的稳定性。今天我们深入探讨三个核心问题:为什么网络字节序一定是大端?Socket 地址结构为什么要强制转换?以及 UDP 核心传输函数的逻辑。


1 ~> 通信的本质 ------ 跨越主机的"进程对话"

在网络编程中,我们必须建立一个核心认知:通信的主体不是主机,而是进程

唯一性标识

  • IP地址定位全球唯一的主机。
  • Port(端口号) 定位主机内部唯一的网络进程。

  • 公式IP + Port = 全网唯一的通信进程

设计解构:为什么不用 PID 代替 Port?

  • 解耦: 进程管理(PID)是系统内核的活,网络通信(Port)是应用层与传输层的约定。如果网络层强依赖 PID,一旦进程重启 PID 变化,整个网络协议栈都会崩溃。

  • 按需分配: 并非所有进程都需要网络通信,只有分配了 Port 的进程才具备"网络身份"。


2 ~> 传输层的抉择------TCP 与 UDP 的性格标签

编写 Socket 程序的第一步,就是选择合适的传输层协议。这决定了你代码的"基调"。

2.1 UDP (用户数据报协议):

  • 特性: 无连接、不可靠、面向数据报。
  • 比喻: 就像写信。写好地址塞进邮箱,至于信丢没丢、对方收没收到,协议本身不关心。

  • 优势: 效率极高,没有握手开销。

2.2 TCP (传输控制协议):

  • 特性: 有连接、可靠传输、面向字节流。

  • 比喻: 就像打电话。必须先接通(三次握手),通话过程中如果有杂音或断线,双方都能立刻感知。

  • 优势: 自动处理丢包、重传和排序,保障数据完整。

2.3 思维导图


3 ~> 网络字节序:关于"共识"

3.1 总结大小端字节序问题

3.1.1 什么是大小端字节序问题

不同硬件架构(如 x86 和 ARM)对多字节数据的存储方式存在分歧,这被称为 "大小端"问题

  • 大端 (Big-Endian): 高位存低地址(符合人类直觉)。

  • 小端 (Little-Endian): 低位存低地址(符合机器加法逻辑)。

  • 网络标准 : TCP/IP 协议族规定,网络数据流一律采用大端序

3.1.2系统级解决方案

为了让同一套代码在不同机器上跑通,我们必须使用系统转换函数:

  • htons (Host to Network Short):将本地 16 位整数转为网络序。

  • ntohs (Network to Host Short):从网络读回数据时转为本地序。

  • 逻辑提示 : 哪怕你的机器本身就是大端序,也应该调用这些函数,这叫代码的可移植性

3.2 为什么不能在报文中带上端标?

有人提议:在数据包里带上一个标志位,告诉对方我是大端还是小端。

  • 结论:这种做法很"挫",为什么"挫"?因为会造成带宽浪费。

    • 带宽浪费:每一帧数据都要多带标志位,累积起来开销巨大。
  • 逻辑冗余:接收方每次都要先判断、再转换,增加了协议解析的复杂度。

3.3 核心价值:建立共识

网络协议的本质就是强制性约束。凡是接入网络的设备,必须遵守统一的规矩。

  • 规则 :单字节不影响,多字节(short, int 等)发送前必须统一转换为大端(Big-Endian)

  • 不服从者:如果不按大端发送,网络层虽然能传,但应用层解析出来的全是乱码。这叫"不听网络言,接入必玩完"。

3.4 为什么选择大端?(大端的微弱优势)

网络选择大端而非小端,主要基于人类阅读习惯

  • 发送逻辑:内存中低地址的数据先发,高地址的后发。

  • 大端表现:在大端模式下,数据的高位存储在低地址。

  • 结果 :当你使用 Wireshark 抓包时,抓到的字节流顺序与我们平时书写十六进制的顺序(如 0x1234)完全一致。这种可读性上的微弱优势,最终让大端成为了网络字节序的终极标准。


4 ~> socket常见API

cpp 复制代码
// 创建 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 ~> sockaddr 接口的"多态"实现

系统需要同时支持"网络通信"和"本地通信",但不想设计两套不同的接口。

5.1 sockaddr 结构

socketAPI是一层抽象的网络编程接口,适用于各种底层网络协议,如IPv4、IPv6,以及后面要介绍的UNIX DomainSocket。然而,各种网络协议的地址格式并不相同。

5.2 结构体家族

  • struct sockaddr_in:专用于 IPv4 网络通信。

  • struct sockaddr_un:专用于 Unix 域间(本地)通信。

5.3 万能基类

cpp 复制代码
struct sockaddr
  • 为了统一接口,所有的 Socket 函数(如 bindconnect)参数类型都是 sockaddr*

  • 底层技巧 : 内核会先读取该结构体的前 16 位(地址族 sa_family),判断是 AF_INET 还是 AF_UNIX,然后再强制转换回具体的类型进行处理。

思考一下: 这种设计类似于 C++ 中的基类指针指向派生类对象,用 C 语言实现了优雅的"接口多态"。


6 ~> 为什么要有 Socket?

Socket 并不是一种协议,它是一个系统级抽象层

  • 向下: 它屏蔽了不同网络协议(IPv4/v6)、不同底层介质(以太网/Wi-Fi)以及不同硬件架构(大小端)的差异。

  • 向上: 它为开发者提供了一套标准的"文件操作"接口。

结语: 好的网络程序,不在于调用了多少 API,而在于理解了每一行代码背后的协议博弈与系统抽象。


结尾

uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| ### 艾莉丝努力练剑 C/C++ & Linux 底层探索者 | 一个正在努力练剑的技术博主 *** ** * ** *** 👀 【关注】 跟随我一起深耕技术领域,见证每一次成长。 ❤️ 【点赞】 让优质内容被更多人看见,让知识传递更有力量。 ⭐ 【收藏】 把核心知识点存好,在需要时随时查、随时用。 💬 【评论】 分享你的经验或疑问,评论区一起交流避坑! 不要忘记给博主"一键四连"哦! "今日练剑达成!" "技术之路难免有困惑,但同行的人会让前进更有方向。" |

结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主"一键四连"哦!

往期回顾

【Linux网络】计算机网络入门:协议不是玄学,从结构体到快递单,彻底搞懂网络封装与通信

🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა

相关推荐
学***54234 小时前
换新电脑如何迁移原有数据?4 种高效数据迁移方法详解
服务器·电脑·负载均衡
是烟花哈9 小时前
【前端】React框架学习
前端·学习·react.js
檀越剑指大厂9 小时前
32 万星的面试学习计划 + 内网穿透工具,程序员面试准备效率翻倍!
学习·面试·职场和发展
vortex59 小时前
Debian 包管理全指南:从底层 dpkg 到高层 apt 及其日志追踪
linux·运维·debian
借雨醉东风9 小时前
程序分享--常见算法/编程面试题:旋转矩阵
c++·线性代数·算法·面试·职场和发展·矩阵
Oll Correct9 小时前
实验二十一:验证OSPF可以划分区域
网络·笔记
偶尔上线经常挺尸9 小时前
《每日一命令08:scp——安全的远程复制》
linux·安全·scp·文件传输·运维基础·远程复制
计算机安禾10 小时前
【Linux从入门到精通】第17篇:日志系统——系统运行的黑匣子
linux·运维·服务器
l1t10 小时前
DeepSeek辅助解决windows 11 wsl2中Linux版Dbeaver显示中文
linux·运维·windows