Linux网络编程- 网络字节顺序
基本概念
网络字节顺序是一种规定的数据表示格式,被用于TCP/IP协议栈,特别是在网络传输数据时。它确保不同的计算机和架构之间可以无缝地通信。网络字节顺序是大端字节序(big-endian)。
字节序的背景
计算机存储多字节数据(例如32位整数、64位整数)时有两种主要方式:大端(big-endian)和小端(little-endian)。
-
大端字节序 (Big-Endian):
- 高位字节存储在内存的低地址。
- 例如,数字
0x12345678
在内存中表示为12 34 56 78
。
-
小端字节序 (Little-Endian):
- 低位字节存储在内存的低地址。
- 例如,数字
0x12345678
在内存中表示为78 56 34 12
。
不同的计算机架构可能使用不同的字节顺序,例如,x86架构使用小端字节序,而早期的Motorola芯片则使用大端字节序。
网络字节顺序的必要性
考虑到不同的计算机可能有不同的字节顺序,TCP/IP协议规定了一个统一的字节顺序来发送和接收数据,称为网络字节顺序。这样,不同的机器在交换数据时就知道如何解释收到的字节。
网络字节顺序是大端字节序。所以,不论系统使用哪种字节顺序,当数据被发送到网络时,它都被转换为大端字节序。接收数据时,数据被转换回主机的字节顺序。
工具函数
为了在网络字节顺序和主机字节顺序之间进行转换,提供了一系列的函数:
htonl()
: 主机到网络长整数转换htons()
: 主机到网络短整数转换ntohl()
: 网络到主机长整数转换ntohs()
: 网络到主机短整数转换
在大端系统上,这些函数通常不做任何事情(因为主机字节顺序已经是大端),而在小端系统上,它们会反转字节顺序。
示例
如果在小端机器上有一个16位的整数 0x1234
,并且想发送它到网络上,可以使用htons()
函数。这会将数字转换为0x3412
。另一台机器从网络上接收到这个数字后,可以使用ntohs()
函数将它转换回其本地表示形式。
htonl、htons、ntohl、ntohs
这四个函数是用于在主机字节顺序和网络字节顺序之间进行转换的。这样不同的计算机架构可以在TCP/IP网络上无缝地通信。让我们详细地看一下每一个函数:
-
htonl()
: 主机到网络长整数转换- 描述: 这个函数将一个无符号长整数(通常是32位)从主机字节顺序转换为网络字节顺序。
- 参数: 一个无符号长整数(如
uint32_t
)。 - 返回值: 参数值转换为网络字节顺序的整数。
-
htons()
: 主机到网络短整数转换- 描述: 这个函数将一个无符号短整数(通常是16位)从主机字节顺序转换为网络字节顺序。
- 参数: 一个无符号短整数(如
uint16_t
)。 - 返回值: 参数值转换为网络字节顺序的整数。
-
ntohl()
: 网络到主机长整数转换- 描述: 这个函数将一个无符号长整数(通常是32位)从网络字节顺序转换为主机字节顺序。
- 参数: 一个无符号长整数(如
uint32_t
)。 - 返回值: 参数值转换为主机字节顺序的整数。
-
ntohs()
: 网络到主机短整数转换- 描述: 这个函数将一个无符号短整数(通常是16位)从网络字节顺序转换为主机字节顺序。
- 参数: 一个无符号短整数(如
uint16_t
)。 - 返回值: 参数值转换为主机字节顺序的整数。
使用场景
当您在网络上发送或接收数据时,使用这些函数非常重要,尤其是当您处理多字节字段(如IP地址、TCP/UDP端口)时。
例如,当您设置一个sockaddr_in
结构的sin_port
字段时,您需要使用htons()
来确保端口号以网络字节顺序存储。类似地,当您从网络上接收数据并想查看其中的端口号或IP地址时,您需要使用相应的ntohs()
或ntohl()
函数。
注意
- "长"和"短"的术语是相对的。在这里,"短"通常指的是16位整数,而"长"通常指的是32位整数。但请注意,这可能会根据平台和编译器实现而有所不同。
- 在大端系统上,这些函数可能不执行任何实际操作,因为这些系统的主机字节顺序已经是网络字节顺序。但为了代码的可移植性和清晰性,仍然建议使用它们。
示例:主机和网络字节顺序的转换
通过下面的例子,我们来演示如何使用htons()
和ntohs()
函数。
#include <stdio.h>
#include <arpa/inet.h> // for htons, ntohsint main() {unsigned short port_host_order = 8080; // 0x1F90 in hexadecimalunsigned short port_network_order;// Convert port number from host byte order to network byte orderport_network_order = htons(port_host_order);printf("Port in host byte order: 0x%X\n", port_host_order);printf("Port in network byte order: 0x%X\n", port_network_order);// Now, let's pretend we received this port number from the network// and we want to convert it back to host byte orderunsigned short received_port_host_order = ntohs(port_network_order);printf("Received port converted back to host byte order: 0x%X\n", received_port_host_order);return 0;
}
这个程序首先定义了一个端口号8080
(它在十六进制中是0x1F90
)。它使用htons()
函数将端口号从主机字节顺序转换为网络字节顺序,并打印出结果。
然后,该程序模拟从网络上接收到这个端口号的情况,并使用ntohs()
函数将它从网络字节顺序转回主机字节顺序。最后,它打印出转换回来的值。
如果在一个小端系统(如大多数x86和x86-64系统)上运行此程序,你可能会看到以下输出:
Port in host byte order: 0x1F90
Port in network byte order: 0x901F
Received port converted back to host byte order: 0x1F90
注意htons
和ntohs
函数如何交换字节,从而在主机和网络字节顺序之间进行转换。
通过下面的例子,我们来演示如何使用htonl()
和ntohl()
函数。
#include <stdio.h>
#include <arpa/inet.h> // for htonl, ntohlint main() {unsigned int ip_address_host_order = 0xC0A80001; // Represents 192.168.0.1 in hexadecimalunsigned int ip_address_network_order;// Convert IP address from host byte order to network byte orderip_address_network_order = htonl(ip_address_host_order);printf("IP Address in host byte order: 0x%X\n", ip_address_host_order);printf("IP Address in network byte order: 0x%X\n", ip_address_network_order);// Now, let's pretend we received this IP address from the network// and we want to convert it back to host byte orderunsigned int received_ip_host_order = ntohl(ip_address_network_order);printf("Received IP Address converted back to host byte order: 0x%X\n", received_ip_host_order);return 0;
}
这个程序首先定义了一个IP地址0xC0A80001
(在十进制中表示为192.168.0.1)。它使用htonl()
函数将IP地址从主机字节顺序转换为网络字节顺序,并打印出结果。
然后,该程序模拟从网络上接收到这个IP地址的情况,并使用ntohl()
函数将它从网络字节顺序转回主机字节顺序。最后,它打印出转换回来的值。
如果在一个小端系统(如大多数x86和x86-64系统)上运行此程序,你可能会看到以下输出:
IP Address in host byte order: 0xC0A80001
IP Address in network byte order: 0x100A8C0
Received IP Address converted back to host byte order: 0xC0A80001
这显示了如何使用htonl
和ntohl
函数在主机和网络字节顺序之间转换32位整数值。
相关文章:
Linux网络编程- 网络字节顺序
基本概念 网络字节顺序是一种规定的数据表示格式,被用于TCP/IP协议栈,特别是在网络传输数据时。它确保不同的计算机和架构之间可以无缝地通信。网络字节顺序是大端字节序(big-endian)。 字节序的背景 计算机存储多字节数据&…...

如何永久关闭WPS任务窗口?
1、按住任务窗口上的浮动按钮,将其拖出来成悬浮窗口。 第二步,使用火绒弹窗拦截,选中弹出的窗口,进行拦截。注意:拦截次数为2次。即进行2次操作。 操作两次后,弹窗被拦截,此时Word文档改为双页显…...
Cesium 问题:加载 geojson 数据量大浏览器会崩,使用primitive方式加载
文章目录 问题分析 问题 之前加载geojson数据都是使用dataSource和entity的方式,但是当数据量大时,浏览器就会崩掉:提示浏览器内存不足,已暂停渲染 分析 使用primitive方式加载数据,可以提高加载渲染效率。实现方法…...

C++ Primer----1.5类简介 章节练习
头文件 Sales_item.h #ifndef SALESITEM_H #define SALESITEM_H #include <iostream> #include <string>class Sales_item{ public:Sales_item(const std::string &book):isbn(book),units_sold(0),revenue(0.0){}Sales_item(std::istream &is){ is >&…...

爬楼梯Java(斐波那契数列)
题目:有n阶楼梯,一次只能爬一层或者两层,请问有多少种方法? 这类题目其实都可以用斐波那契数列来解决,比如: 一阶楼梯只有一种方法 二阶楼梯有(11,2)两种方法 三阶楼梯有(111,12,21)三种方法 四阶楼梯有(1111,121,112,22,211)五种方式 五阶楼梯有(11111,1112,122,1211,1…...

Maven项目package为jar包后在window运行报A JNI error has occurred
原因:本地java版本与项目结构中使用的java版本不一致(之前因为别的需求把idea的java版本改为了18) 解决方法 打开项目结构,将idea的java版本改为与本地一致 再修改项目中的pom.xml 重新编译,package即可...

iview 的table表格组件使单元格可编辑和输入
表格的列定义中,在需要编辑的字段下使用render函数 template表格组件 <Table border :data"data" :columns"tableColumns" :loading"loading"></Table>data中定义table对象 table: {tableColumns: [{title: 商品序号,k…...

统计的基本概念及抽样分布
文章目录 🍋引言🍋总体(Population)🍋总体参数 🍋样本(Sample)🍋随机样本🍋样本统计量 🍋统计量(Statistic)🍋…...
【C++】class的设计与使用(四)this指针
this指针 this作用域是在类内部,只能在成员函数中使用;this在成员函数的开始前构造,在成员函数的结束后清除;编译器在编译的时候也会自动加上this,它作为非静态成员函数的隐含形参,对各成员的访问均通过th…...

mysql 导入sql文件
mysql 导入sql文件 sudo mysql -uroot -p123456 -h127.0.0.1 sudo mysql -uroot -p123456 -h127.0.0.1然后 show databases;然后 use 数据库名称; 然后 source 20230920031001.sql;如果不加 -h127.0.0.1 可能会出现错误 /var/lib/mysql.sock error 通过 navicat导入的话&am…...

springcloud:三、ribbon负载均衡原理+调整策略+饥饿加载
Ribbon负载均衡原理 调整Ribbon负载均衡策略 第一种会对order-service里所有的服务消费者都采用该新规则 第二种会针对order-service里某个具体的服务消费者采用该新规则 饥饿加载...
【Unity编辑器扩展】Tranform组件自定义扩展,复制位置旋转缩放数据
目录 一、Tranform组件数据的扩展 二、 RectTransform组件数据的扩展 很多时候我们在做Tranform属性配置的时候需要反复的获取对象的位置信息,旋转信息。这个时候有个方便的工具会使得我们的效率大大提升。 一、Tranform组件数据的扩展 1.可以复制世界坐标,世界旋转 V…...
自动驾驶领域中的CMS系统应用探讨
由佐思汽研主办的“ ICVS汽车智能网联大会”正式启幕,邀请Tier1、软件供应商、操作系统商、智能驾驶及智能驾舱相关企业,共同探讨行业现状、创新技术应用交流、以及未来行业发展趋势等。 赛格导航视频产品线总监刘玉龙应邀参加本次大会,并发…...

十分钟理解OSPF路由协议
十分钟理解OSPF路由协议 1.RIP的缺陷以跳数为度量值最大跳数为15更新路由表采用全更新收敛速度慢 2.RIP与OSPF比较OSPF概述运行OSPF协议之前运行OSPF协议之后 3.OSPF协议工作过程1.发现邻居2.建立邻接关系3.传递链路状态信息4.计算路由 4.OSPF分区域管理 有RIP协议,…...
Python 编程基础 | 第一章-预备知识 | 1.4、包管理工具
一、包管理工具 1、pip简介 pip是Python自带的包管理器,它可以帮助我们安装、升级和卸载Python包。Python包是一组Python模块,它们可以提供各种功能,例如数据分析、Web开发、机器学习等等。pip可以让我们轻松地安装这些包,以便我…...

delphi中使用CADVCL 10.0 Enterprise控件解析DXF文件生成图片保存到本地
使用案例demos中GettingStarted案例 修改OnClick方法 更换代码 varvDrawing: TsgCADDXFImage;I: Integer;vEnt: TsgDXFEntity;vDXFImage:TsgCADImage;Bitmap: TBitmap;jpg: TJpegImage; beginvDrawing : TsgCADDXFImage.Create;vDrawing.LoadFromFile(d:\Entities.dxf);for …...

Hazelcast系列(三):hazelcast管理中心
系列文章 Hazelcast系列(一):初识hazelcast Hazelcast系列(二):hazelcast集成 Hazelcast系列(三):hazelcast管理中心 目录 前言 平台搭建 测试 其他 参考 总结 前言 前面,我们通过几种配置方式(Hazelcast系…...

QT 绘画功能的时钟
.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPaintEvent> #include <QDebug> //信息调试类 #include <QPainter> #include <QPixmap> //图像引擎类 #include <QTime> #include <QTimer> …...

设计模式之道-模板方法模式
文章目录 模板方法模式简介作用模板方法模式的缺点模板方法模式的应用场景业务场景开源框架中的应用 对比回调和Hook模式关于组合优先于继承 关于设计模式乱用的现象 模板方法模式 简介 模板方法模式是一种行为型设计模式,该设计模式的核心在于通过抽象出一套相对…...
头哥的实践平台的Linux文件/目录管理
一 Linux 文件/目录管理 1.本关的编程任务是补全右侧代码片段中Begin至End中间的代码,具体要求如下: 新创建两个文件空文件file1和file2。 删除系统已存在的两个文件oldFile1和oldFile2。 #!/bin/bash#在以下部分写出完成任务的命令 #***********begi…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...