网络编程---UDP协议与IP协议

发布于:2025-07-24 ⋅ 阅读:(22) ⋅ 点赞:(0)

UDP协议基础概念

UDP(User Datagram Protocol,用户数据报协议)是 TCP/IP 协议栈中无连接、不可靠、高效的传输层协议,与 TCP 的 “可靠传输” 设计不同,UDP 更注重传输效率,适用于对实时性要求高但可容忍少量数据丢失的场景。

UDP 的核心特性

  • 无连接

    • 通信前无需建立连接(无三次握手),发送方直接封装数据并发送,接收方直接接收,流程简单。
    • 示例:类似 “写信”,无需提前确认对方是否准备好,直接投递即可。
  • 不可靠传输

    • 不保证数据的交付:数据可能丢失、重复或乱序到达,UDP 协议本身不提供重传机制。
    • 不提供流量控制和拥塞控制:发送方按自身速率发送,不考虑接收方和网络的承载能力。
  • 面向数据报

    • 数据以 “数据报” 为单位传输,每个数据报独立封装(包含完整的源地址、目的地址等信息)。
    • 接收方一次读取一个完整的数据报,保留数据边界(不会像 TCP 那样合并或拆分数据)。
  • 高效轻量

    • 头部开销小:UDP 头部仅 8 字节(TCP 头部至少 20 字节),包含源端口、目的端口、数据长度、校验和 4 个字段。
    • 处理速度快:无需维护连接状态、重传队列等,协议栈处理逻辑简单,延迟低。

UDP 数据报结构(头部 + 数据)

字段 长度(字节) 含义
源端口 2 发送方端口号(可选,0 表示不需要回复)
目的端口 2 接收方端口号(用于定位目标进程)
数据报长度 2 整个 UDP 数据报的总长度(头部 + 数据,最大值 65535 字节)
校验和 2 用于校验数据在传输中是否损坏(可选,全 0 表示不校验)
数据部分 可变 应用层传递的数据(最大长度 = 65535-8=65527 字节)

 

UDP 与 TCP 的核心区别

特性 UDP TCP
连接性 无连接(发送前无需建立连接) 面向连接(需三次握手建立连接)
可靠性 不可靠(不保证交付、无重传) 可靠(确认、重传、按序交付)
数据边界 保留(一次读一个完整数据报) 无边界(字节流,可能粘包)
头部开销 小(8 字节) 大(至少 20 字节)
传输效率 高(延迟低、资源消耗少) 较低(需维护连接和重传机制)
适用场景 实时通信(音视频、游戏) 可靠传输(文件、网页、邮件)

UDP协议常用函数

Socket套接字用法与TCP相似
发送sendto()

如果在面向连接的套接字(SOCK_STREAM 或 SOCK_SEQPACKET 类型)上使用 sendto (),则 dest_addr 和 addrlen 参数会被忽略(且当这些参数不为 NULL 和 0 时,可能返回 EISCONN 错误);若套接字实际未建立连接,则返回 ENOTCONN 错误。否则(对于无连接套接字),目标地址由 dest_addr 给出,其大小由 addrlen 指定。

#include <sys/types.h>
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen);
sockfd:通过 socket() 创建的套接字文件描述符(UDP 套接字或 TCP 套接字)
buf:(const void *)指向待发送数据的缓冲区指针(应用程序要发送的数据存储在这里)
len:要发送的数据长度(字节数),即 buf 中有效数据的大小
flags:发送选项标志,与 send() 相同(如 MSG_OOB 发送紧急数据、MSG_DONTWAIT 非阻塞发送等),通常设为 0
dest_addr:const struct sockaddr *(需根据协议族强转为对应类型,如 IPv4 用 struct sockaddr_in)
指向目标地址结构的指针,包含接收方的 IP 地址和端口号(对 UDP 必填,对 TCP 可选)
addrlen:dest_addr 指向的地址结构的大小(字节数),如 sizeof(struct sockaddr_in)

RETURN VALUE
       On success, these calls return the number of bytes sent.  On error, -1 is returned, and errno is set appropriately.
接收recvfrom()

recvfrom () 将接收到的消息放入缓冲区 buf 中。调用者必须在 len 中指定缓冲区的大小。

如果 src_addr 不为 NULL,且底层协议提供了消息的源地址,那么该源地址会被存入 src_addr 所指向的缓冲区。在这种情况下,addrlen 是一个 “值 - 结果参数”:调用前,它应被初始化为与 src_addr 关联的缓冲区大小;返回时,addrlen 会被更新为源地址的实际大小。如果提供的缓冲区过小,返回的地址会被截断,此时 addrlen 返回的值将大于调用时传入的值。

如果调用者不需要源地址,src_addr 和 addrlen 应设为 NULL。

#include <sys/types.h>
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);
sockfd:通过 socket() 创建的套接字文件描述符(UDP 或 TCP 套接字)
buf:(void *)指向接收缓冲区的指针,用于存储接收到的数据
len:接收缓冲区的大小(字节数),即最多能接收的数据量
flags:接收选项标志,与 recv() 相同(如 MSG_PEEK 预览数据、MSG_WAITALL 阻塞等待完整数据等),通常设为 0
src_addr:struct sockaddr *(输出参数,需提前分配空间并强转为对应类型,如 IPv4 用 struct sockaddr_in *)用于存储发送方的地址信息(IP 地址和端口号)。若无需获取发送方地址,可设为 NULL
addrlen:socklen_t *(输入输出参数)
输入:src_addr 指向的地址结构的大小(如 sizeof(struct sockaddr_in))
输出:实际存储的发送方地址结构的大小(可能小于输入值)
若 src_addr 为 NULL,addrlen 也应设为 NULL

IP协议

IP协议基础概念

 IP,指网际互连协议,Internet Protocol的缩写,是TCP/IP体系中的网络层协议。

设计IP的目的是提高网络的可扩展性:

一是解决互联网问题,实现大规模、异构网络的互联互通;

二是分割顶层网络应用和底层网络技术之间的耦合关系,以利于两者的独立发展。根据端到端的设计原则,IP只为主机提供一种无连接、不可靠的、尽力而为的数据包传输服务。

IP 协议的核心作用是实现不同网络之间的数据报(Datagram)传输,具体包括:

寻址:通过 IP 地址标识网络中的设备,确保数据能准确发送到目标节点。

路由选择:通过路由算法确定数据从源到目标的最佳路径(可能经过多个中间节点)。

分片与重组:当数据报大小超过网络链路的最大传输单元(MTU)时,将其分割为小分片,到达目标后重组。

子网掩码(Subnet Mask)

子网掩码是一个 32 位的二进制数,与 IP 地址配合使用,用于划分 IP 地址中的网络部分和主机部分,是实现子网划分的核心工具。

核心作用:
  • 区分网络位与主机位

    子网掩码中,“1” 对应的 IP 地址部分为网络位,“0” 对应的部分为主机位。例如:

    • IP 地址:192.168.1.100(二进制:11000000.10101000.00000001.01100100
    • 子网掩码:255.255.255.0(二进制:11111111.11111111.11111111.00000000
      则网络位为前 24 位(192.168.1),主机位为后 8 位(100)。
  • 判断两台设备是否在同一子网

    若两台设备的 IP 地址与子网掩码进行 “与运算” 后结果(网络号)相同,则它们处于同一子网,可直接通信;否则需通过网关转发。

网关(Gateway)

网关是不同网络之间的连接点或转发设备,本质是一个具有路由功能的 IP 地址(通常是路由器的局域网 IP),负责在不同子网或网络类型(如局域网与互联网)之间转发数据。

核心作用:
  • 跨子网通信

    当设备需要与不同子网的设备通信时,数据会先发送到网关,再由网关转发到目标网络。例如:

    • 局域网内设备(192.168.1.100)访问互联网时,数据会先发送到网关(如192.168.1.1),再由网关转发到公网。
  • 协议转换

    网关可在不同协议的网络(如以太网与 Wi-Fi)之间转换数据格式,确保通信兼容。

DNS 服务器(Domain Name System Server)

DNS 服务器是负责域名与 IP 地址转换的服务器,相当于网络中的 “通讯录”。

核心作用:
  • 域名解析

    人类习惯使用域名(如www.baidu.com)访问网站,而计算机依赖 IP 地址(如180.101.50.242)通信。DNS 服务器会将域名解析为对应的 IP 地址,反之也可将 IP 地址反向解析为域名。

  • 加速访问

    DNS 服务器会缓存解析结果,重复访问同一域名时可直接使用缓存,减少解析时间。

常见 DNS 服务器:
  • 公共 DNS:如阿里云(223.5.5.5)、谷歌(8.8.8.8)、114DNS(114.114.114.114)。
  • 本地 DNS:由网络服务商(ISP)提供,默认自动分配,解析速度通常较快。

eg:通过ping命令,查看本地机是否能够访问百度

三者的关系与协同工作

  • 子网掩码确定设备是否在同一子网,决定数据是否需要网关转发;
  • 网关负责跨网络数据的转发,是局域网接入外部网络的 “大门”;
  • DNS 服务器解决 “域名到 IP” 的转换问题,让用户无需记忆复杂的 IP 地址即可访问网络。

IP 地址结构

IPv4地址结构

IPv4 地址为 32 位二进制数,通常以点分十进制形式表示(将 32 位分为 4 组 8 位二进制,每组转换为 0-255 的十进制,用小数点分隔,如192.168.1.1)。其核心是通过网络号主机号区分设备所属网络及自身标识,划分方式经历了 “分类地址” 到 “无类别域间路由(CIDR)” 的演变。

分类地址(传统划分方式,已基本淘汰)

早期 IPv4 按地址前缀将地址分为 5 类,直接通过首几位二进制判断网络类型,固定网络号和主机号长度:

类别 首几位二进制 地址范围(十进制) 网络号长度 主机号长度 适用场景
A 类 0 0.0.0.0 - 127.255.255.255 8 位 24 位 大型网络(支持约 1600 万主机)
B 类 10 128.0.0.0 - 191.255.255.255 16 位 16 位 中型网络(支持约 6.5 万台主机)
C 类 110 192.0.0.0 - 223.255.255.255 24 位 8 位 小型网络(支持约 254 台主机)
D 类 1110 224.0.0.0 - 239.255.255.255 - - 多播地址(用于一组设备通信)
E 类 1111 240.0.0.0 - 255.255.255.255 - - 保留用于实验
  • 缺陷:分类地址导致地址浪费严重(如 A 类网络仅分配 126 个,却占用约 50% 的总地址空间),无法灵活适应不同规模网络。
无类别域间路由(CIDR,当前主流方式)

为解决分类地址的局限性,CIDR 采用可变长子网掩码(VLSM),通过 “网络前缀长度” 灵活划分网络号和主机号,格式为IP地址/前缀长度(如192.168.1.0/24)。

  • 前缀长度:表示前 n 位为网络号(n 的范围 0-32),剩余(32-n)位为主机号。
  • 子网掩码:与 IP 地址配合使用,通过 32 位二进制中 “1” 的位置标识网络号(如/24对应子网掩码255.255.255.0,前 24 位为 1)。

示例

  • 192.168.1.0/24:前 24 位为网络号(192.168.1),后 8 位为主机号(可分配 254 个主机地址:192.168.1.1192.168.1.254)。
  • 10.0.0.0/16:前 16 位为网络号(10.0),后 16 位为主机号(可分配 65534 个主机地址)。

特殊 IP 地址

  • 网络地址:主机号全为 0 的地址(如192.168.1.0/24),标识整个网络本身,不可分配给设备。
  • 广播地址:主机号全为 1 的地址(如192.168.1.255/24),用于向网络内所有设备发送数据。
  • 回环地址127.0.0.0/8网段(如127.0.0.1),用于设备自身测试(数据不经过物理网络)。
  • 私有地址:仅用于局域网,需通过 NAT 转换为公网地址访问互联网,包括:10.0.0.0/8(A 类私有)172.16.0.0/12(B 类私有)192.168.0.0/16(C 类私有)

IPv6 地址结构

IPv6 地址为 128 位二进制数,以冒分十六进制形式表示(将 128 位分为 8 组 16 位二进制,每组转换为 0-FFFF 的十六进制,用冒号分隔,如2001:0db8:85a3:0000:0000:8a2e:0370:7334)。其结构设计更灵活,支持自动配置和海量地址,且取消了分类概念,通过前缀区分网络。

表示规则(简化书写)
  • 省略前导零:每组中开头的 0 可省略(如000000db8db8)。
  • 压缩连续零组:用::代替一组或多组连续的0000(仅能出现一次),如2001:0db8:0:0:0:8a2e:370:7334可简写为2001:db8::8a2e:370:7334
地址结构与前缀

IPv6 地址通过前缀长度(类似 CIDR)划分网络号和接口标识,格式为IPv6地址/前缀长度(如2001:db8::/32)。

  • 前缀长度范围 0-128,前 n 位为网络号,剩余(128-n)位为接口标识(类似主机号)。
  • 接口标识通常由设备 MAC 地址转换生成(通过 EUI-64 格式),支持自动配置(无需 DHCP)。
特殊 IPv6 地址
  • 未指定地址::(128 位全为 0),表示 “无地址”,通常用于设备初始化时。
  • 回环地址::1,功能同 IPv4 的127.0.0.1,用于本地测试。
  • 链路本地地址:前缀为fe80::/10,仅在本地链路(如同一局域网)内有效,用于邻居发现等本地通信,不路由到公网。
  • 多播地址:前缀为ff00::/8,用于向一组设备发送数据(替代 IPv4 的广播),如ff02::1表示本地链路内所有节点。
特性 IPv4 IPv6
地址长度 32 位(4 个字节) 128 位(16 个字节)
地址格式 点分十进制(如 192.168.1.1) 冒分十六进制(如 2001:0db8::1)
地址数量 约 43 亿个(已耗尽) 约 3.4×10³⁸个(几乎无限)
头部字段 包含校验和、选项等(可变长度) 简化头部(固定长度),无校验和
安全性 依赖上层协议(如 SSL/TLS) 内置 IPsec(加密和认证)
广播支持 支持广播地址 无广播,用多播替代

IP 协议的局限性

  • 无连接:发送数据前无需建立连接,无法保证数据的可靠到达(可能丢失、重复或乱序),需依赖 TCP 等上层协议提供可靠性。
  • 无状态:路由器不记录数据报的传输状态,每次转发独立处理,灵活性高但难以实现复杂控制。

IP 协议的应用与延伸

  • NAT(网络地址转换):在 IPv4 中,通过将私有地址转换为公有地址,缓解公网地址不足的问题。
  • 路由协议:如 OSPF、BGP 等,配合 IP 协议计算最佳路径,实现跨网络数据传输。
  • IPv6 过渡技术:如双栈(设备同时支持 IPv4 和 IPv6)、隧道(将 IPv6 数据报封装在 IPv4 中传输),实现两种协议的平滑过渡。

在Linux系统中查看网络信息

netstat 是用于查看网络连接、路由表、接口统计等网络相关信息的命令行工具
参数:

-a:显示所有网络连接(包括 TCP、UDP)及监听状态(LISTEN),包含已建立的连接和等待连接的服务,示例输出会包含 LISTEN(监听中)、ESTABLISHED(已连接)等状态

-t:仅显示 TCP 协议相关的连接和服务,不包含 UDP

-u:仅显示 UDP 协议相关的连接和服务,不包含 TCP

-n:以数字形式显示 IP 地址和端口(而非域名或服务名,如显示 192.168.1.1:80 而非 example.com:http),加快查询速度

-l:仅显示处于 监听状态(LISTEN) 的服务,通常用于查看当前服务器开放的端口(如 Web 服务的 80 端口、SSH 的 22 端口等)

组合命令:

  • netstat -tuln
    最常用的组合:显示所有 TCP(-t) 和 UDP(-u) 的 监听状态(-l) 服务,并以 数字形式(-n) 展示 IP 和端口
    适合快速查看本机开放的端口及对应服务。

  • netstat -an
    显示所有连接(-a),包括已建立的连接和监听状态,并用数字形式(-n)展示,适合排查网络连接问题

  • netstat -tn
    仅显示 TCP 协议的连接,以数字形式展示,可用于查看当前的 TCP 连接详情(如客户端 IP、端口等)

 

数据链路层 

数据链路层是 OSI 七层模型中的第二层,位于物理层之上、网络层之下,主要负责在相邻两个网络节点之间(如两个路由器、计算机与路由器之间)通过物理链路提供可靠的数据传输。它将物理层传输的原始比特流封装成帧,通过差错控制、流量控制等机制,确保数据在链路中准确、有序地传输。

MAC 地址

MAC 地址(Media Access Control Address,介质访问控制地址)是网络设备(如网卡、路由器接口等)在数据链路层用于唯一标识自身的物理地址,相当于设备在网络中的 “身份证”,确保数据能在同一链路中准确送达目标设备。

MAC 地址的基本特性
  • 唯一性

    • 全球范围内,每个网络设备的 MAC 地址由生产厂商向 IEEE(国际电气和电子工程师协会)申请,确保全球唯一
    • eg:同一品牌的两块网卡,MAC 地址绝对不同。
  • 固化性与可修改性

    • 通常被烧录在网卡的 ROM 中,称为 “物理地址”,出厂后固定不变(即 “烧录地址”)。
    • 但操作系统允许通过软件临时修改 MAC 地址(如 Windows 的注册表、Linux 的 ifconfig 命令),用于隐私保护或网络准入绕过。
MAC 地址的格式与结构

MAC 地址为48 位二进制数,通常以6 组十六进制数表示,每组 2 位,组间用冒号(:)或连字符(-)分隔。eg:

  • 00:1A:2B:3C:4D:5E(冒号分隔)
  • 00-1A-2B-3C-4D-5E(连字符分隔)

48 位地址可分为两部分:

  • 前 24 位:OUI(组织唯一标识符)
    • 由 IEEE 分配给网络设备制造商,代表生产厂商。eg: 00:1A:2B可能对应某品牌网卡厂商。
  • 后 24 位:厂商自定义编号
    • 由厂商自行分配给每台设备,确保同厂商内不重复。

MAC 地址能否跨网络使用?
不能。MAC 地址仅在本地链路(同一广播域)有效,当数据通过路由器转发到其他网络时,帧的源 / 目的 MAC 地址会被路由器替换(仅保留 IP 地址不变)。

如何查看设备的 MAC 地址?

Windows:命令提示符输入 ipconfig /all,查看 “物理地址”

Linux/macOS:终端输入 ifconfig 或 ip link,查看 “ether” 字段

数据链路层的核心功能

  • 帧封装与拆封

    • 将网络层传来的数据包(如 IP 数据报)加上帧头(包含源 / 目的 MAC 地址、控制信息等)和帧尾(校验字段),形成 “帧”,作为数据链路层的传输单位。
    • 接收端拆封帧,去除头部和尾部,将数据部分交给上层(网络层)。
  • 差错控制

    • 通过校验机制(如 CRC 循环冗余校验)检测帧在传输中是否因噪声、干扰等出现错误。
    • 若检测到错误,通过重传机制(如 ARQ 自动重传请求)要求发送方重新发送出错的帧,确保数据正确性。
  • 流量控制

    • 防止发送方发送数据过快,导致接收方因缓冲区不足而丢失数据。
    • 常见机制:滑动窗口协议(如 GBN 回退 N 帧、SR 选择重传),通过控制发送窗口大小限制发送速率。
  • 链路管理

    • 负责数据链路的建立、维护和释放(如点对点协议 PPP 中的链路协商过程)。
  • MAC 地址寻址

    • 通过帧头中的 MAC 地址(物理地址)识别同一链路中的不同节点,确保数据发送到正确的接收方(区别于网络层的 IP 地址寻址)。

数据链路层的重要协议与技术

  • 点对点协议(PPP)

    • 用于点对点链路(如拨号上网、路由器之间的专线),支持多种网络层协议(IP、IPX 等),包含链路控制协议(LCP)和网络控制协议(NCP)。
  • 以太网协议(Ethernet)

    • 局域网(LAN)中最常用的技术,基于共享信道,核心是 CSMA/CD(载波监听多路访问 / 冲突检测)机制:
      • 发送前监听信道,若空闲则发送;若忙碌则等待。
      • 发送中检测到冲突(多个节点同时发送),立即停止并发送干扰信号,避免数据混乱,随后通过退避算法重传。
  • 无线局域网协议(如 802.11)

    • 针对无线信道的特殊性(易受干扰、信号衰减),采用 CSMA/CA(载波监听多路访问 / 冲突避免)机制,通过 RTS/CTS 握手减少冲突。

ARP地址解析协议

ARP(Address Resolution Protocol,地址解析协议)是 TCP/IP 协议栈中的核心协议之一,工作在数据链路层和网络层之间,主要功能是将网络层的 IP 地址映射为数据链路层的 MAC 地址,确保数据帧能在局域网内准确送达目标设备。

ARP 的核心作用

在局域网通信中,网络层使用 IP 地址进行逻辑寻址(如确定 “发送到哪个网络节点”),而数据链路层需要 MAC 地址进行物理寻址(如确定 “通过网卡发送给哪个设备”)。ARP 协议的核心功能就是在已知目标 IP 地址的情况下,获取其对应的 MAC 地址,建立 IP 地址与 MAC 地址的映射关系,从而完成数据帧的封装和传输。

ARP 的工作原理与流程

ARP 的工作过程基于 “请求 - 应答” 机制,可分为ARP 请求和ARP 应答两个阶段

以主机 A 向同一局域网内的主机 B 发送数据为例:

  • 检查 ARP 缓存

    主机 A 需要向主机 B(IP 地址:192.168.1.2)发送数据时,首先检查本地的ARP 缓存表(存储近期 IP 与 MAC 的映射关系,有超时机制,通常为 15-300 秒)。

    • 若缓存中存在 192.168.1.2 对应的 MAC 地址,则直接使用该 MAC 地址封装数据帧并发送。
    • 若缓存中不存在,则触发 ARP 请求流程。
  • 发送 ARP 请求广播

    主机 A 构造一个ARP 请求帧,主要包含:

    • 源 IP 地址(主机 A 的 IP:192.168.1.1)和源 MAC 地址(主机 A 的 MAC:00:1A:2B:3C:4D:5E);
    • 目标 IP 地址(主机 B 的 IP:192.168.1.2)和目标 MAC 地址(暂为广播地址:FF:FF:FF:FF:FF:FF)。
      该帧通过广播方式发送到局域网内的所有设备(因为目标 MAC 是广播地址,所有设备都会接收),内容可理解为:“谁拥有 IP 地址 192.168.1.2?请把你的 MAC 地址告诉我(192.168.1.1,00:1A:2B:3C:4D:5E)”。
  • 接收并处理 ARP 请求

    局域网内所有设备收到 ARP 请求帧后,会检查帧中的目标 IP 地址是否与自身 IP 匹配:

    • 非目标设备(如主机 C、D)发现 IP 不匹配,直接丢弃该帧。
    • 目标设备(主机 B)发现 IP 匹配,会将主机 A 的 IP 与 MAC 映射关系存入自己的 ARP 缓存(便于后续向 A 发送数据时直接使用),然后构造ARP 应答帧
  • 发送 ARP 应答单播

    主机 B 的 ARP 应答帧包含:

    • 源 IP 地址(主机 B 的 IP:192.168.1.2)和源 MAC 地址(主机 B 的 MAC:AA:BB:CC:DD:EE:FF);
    • 目标 IP 地址(主机 A 的 IP:192.168.1.1)和目标 MAC 地址(主机 A 的 MAC:00:1A:2B:3C:4D:5E)。
      该帧通过单播方式直接发送给主机 A,内容可理解为:“我是 192.168.1.2,我的 MAC 地址是 AA:BB:CC:DD:EE:FF”。
  • 更新 ARP 缓存并通信

    主机 A 收到应答帧后,将主机 B 的 IP 与 MAC 映射关系存入 ARP 缓存,随后即可使用该 MAC 地址封装数据帧,向主机 B 发送数据。

反向 ARP(RARP)
通过 MAC 地址查询对应的 IP 地址。早期用于无盘工作站(无本地存储,无法预先配置 IP),工作站启动时发送 RARP 请求(包含自身 MAC),向 RARP 服务器申请 IP 地址。

硬件设备:

交换机(Switch)是局域网(LAN)中的核心网络设备,工作在 OSI 模型的数据链路层(第二层),主要功能是根据 MAC 地址转发数据帧,实现多个设备之间的高效、安全通信。与集线器(Hub)的 “广播转发” 不同,交换机通过学习 MAC 地址并构建转发表,实现 “点对点” 的数据转发,大幅提升网络性能。

网络字节序与主机字节序

在网络通信中,不同设备(如计算机、路由器)可能采用不同的字节存储顺序,这会导致数据传输时出现混乱(例如,一个 32 位整数在不同设备上可能被解析为不同的值)。为解决这一问题,引入了网络字节序主机字节序的概念。

  • 主机字节序(Host Byte Order)

    指计算机 CPU 内部存储多字节数据(如 int、long)时的字节顺序,由硬件架构决定,不同设备可能不同。常见的主机字节序有两种:

    注意:单字节数据(如 char)不存在字节序问题,因为只有一个字节。

    • 小端序(Little-Endian):低位字节存于内存低地址,高位字节存于内存高地址。
      例如:整数0x12345678(十六进制)在小端序中存储为78 56 34 12(从低地址到高地址)。
    • 大端序(Big-Endian):高位字节存于内存低地址,低位字节存于内存高地址。
      例如:整数0x12345678在大端序中存储为12 34 56 78(从低地址到高地址)。
  • 网络字节序(Network Byte Order)

    为统一网络中数据的传输格式,规定所有网络协议必须使用大端序作为标准字节序,即网络字节序 = 大端序。

    无论发送端和接收端的主机字节序是大端还是小端,传输前都需将数据转换为网络字节序,接收后再转换为本地主机字节序。

字节序转换的常用函数

函数名 功能 适用场景
htons() 主机字节序 → 网络字节序(16 位整数,如端口号) 转换端口号(16 位)
ntohs() 网络字节序 → 主机字节序(16 位整数) 解析接收到的端口号
htonl() 主机字节序 → 网络字节序(32 位整数,如 IP 地址) 转换 IP 地址(32 位)
ntohl() 网络字节序 → 主机字节序(32 位整数) 解析接收到的 IP 地址
#include <arpa/inet.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

注:函数名中,h=host(主机),n=network(网络),s=short(16 位),l=long(32 位) 

结语:

无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力


    网站公告

    今日签到

    点亮在社区的每一天
    去签到