网络数据传输时的大小端问题

2023-05-16

  socket网络字节序以及大端序小端序
  不同CPU中,4字节整数1在内存空间的存储方式是不同的。4字节整数1可用2进制表示如下:
  
  00000000 00000000 00000000 00000001

  有些CPU以上面的顺序存储到内存,另外一些CPU则以倒序存储,如下所示:

  
 00000001 00000000 00000000 00000000

  若不考虑这些就收发数据会发生问题,因为保存顺序的不同意味着对接收数据的解析顺序也不同。
  

  大端序和小端序

 CPU向内存保存数据的方式有两种:

  
大端序(Big Endian):高位字节存放到低位地址(高位字节在前)。
小端序(Little Endian):高位字节存放到高位地址(低位字节在前)。


   仅凭描述很难解释清楚,不妨来看一个实例。假设在 0x20 号开始的地址中保存4字节 int 型数据 0x12345678,大端序CPU保存方式如下图所示:

  

  图1:整数 0x12345678 的大端序字节表示
  


  对于大端序,最高位字节 0x12 存放到低位地址,最低位字节 0x78 存放到高位地址。小端序的保存方式如下图所示

 

 

不同CPU保存和解析数据的方式不同(主流的Intel系列CPU为小端序),小端序系统和大端序系统通信时会发生数据解析错误。因此在发送数据前,要将数据转换为统一的格式——网络字节序(Network Byte Order)。网络字节序统一为大端序。

主机A先把数据转换成大端序再进行网络传输,主机B收到数据后先转换为自己的格式再解析。
  

网络字节序转换函数

在《使用bind()和connect()函数》一节中讲解了 sockaddr_in 结构体,其中就用到了网络字节序转换函数,如下所示:

//创建sockaddr_in结构体变量
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));  //每个字节都用0填充
serv_addr.sin_family = AF_INET;  //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");  //具体的IP地址
serv_addr.sin_port = htons(1234);  //端口号

  htons() 用来将当前主机字节序转换为网络字节序,其中h代表主机(host)字节序,n代表网络(network)字节序,s代表short,htons 是 h、to、n、s 的组合,可以理解为”将short型数据从当前主机字节序转换为网络字节序“。

  常见的网络字节转换函数有:

htons():host to network short,将short类型数据从主机字节序转换为网络字节序。
ntohs():network to host short,将short类型数据从网络字节序转换为主机字节序。
htonl():host to network long,将long类型数据从主机字节序转换为网络字节序。
ntohl():network to host long,将long类型数据从网络字节序转换为主机字节序。


  通常,以s为后缀的函数中,s代表2个字节short,因此用于端口号转换;以l为后缀的函数中,l代表4个字节的long,因此用于IP地址转换。

  举例说明上述函数的调用过程:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

int main(){
    unsigned short host_port = 0x1234, net_port;
    unsigned long host_addr = 0x12345678, net_addr;

    net_port = htons(host_port);
    net_addr = htonl(host_addr);

    printf("Host ordered port: %#x\n", host_port);
    printf("Network ordered port: %#x\n", net_port);
    printf("Host ordered address: %#lx\n", host_addr);
    printf("Network ordered address: %#lx\n", net_addr);

    system("pause");
    return 0;
}


  运行结果:

  Host ordered port: 0x1234

  Network ordered port: 0x3412

  Host ordered address: 0x12345678
  Network ordered address: 0x78563412

  另外需要说明的是,sockaddr_in 中保存IP地址的成员为32位整数,而我们熟悉的是点分十进制表示法,例如 127.0.0.1,它是一个字符串,因此为了分配IP地址,需要将字符串转换为4字节整数。

  inet_addr() 函数可以完成这种转换。inet_addr() 除了将字符串转换为32位整数,同时还进行网络字节序转换。请看下面的代码:

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")

int main(){
    char *addr1 = "1.2.3.4";
    char *addr2 = "1.2.3.256";

    unsigned long conv_addr = inet_addr(addr1);
    if(conv_addr == INADDR_NONE){
        puts("Error occured!");
    }else{
        printf("Network ordered integer addr: %#lx\n", conv_addr);
    }

    conv_addr = inet_addr(addr2);
    if(conv_addr == INADDR_NONE){
        puts("Error occured!");
    }else{
        printf("Network ordered integer addr: %#lx\n", conv_addr);
    }

    system("pause");
    return 0;
}


  运行结果:

  Network ordered integer addr: 0x4030201

  Error occured!

  从运行结果可以看出,inet_addr() 不仅可以把IP地址转换为32位整数,还可以检测无效IP地址。

注意:为 sockaddr_in 成员赋值时需要显式地将主机字节序转换为网络字节序,而通过 write()/send() 发送数据时TCP协议会自动转换为网络字节序,不需要再调用相应的函数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

网络数据传输时的大小端问题 的相关文章

  • 运行内存变成的2G,为硬件保留内存为6G

    运行内存变成的2G xff0c 为硬件保留内存为6G 先看设置中下面是否有设置是否激活windows xff0c 如有点进去 xff0c 有疑难解疑下面 xff0c 点入会自动激活windows xff0c 如盗版就不行 xff0c 激活后
  • ubuntu20.4安装NVIDIA驱动,cuda

    安装NVIDIA驱动准备工作 下载NVIDIA地址 xff1a https www nvidia cn Download index aspx lang 61 cn 查看是否安装好驱动命令 xff1a nvidia span class t
  • 图像进行反转:白变黑,黑变白

    图像进行反转 xff1a 白变黑 xff0c 黑变白 二值图对图像进行反转 span class token keyword import span cv2 img span class token operator 61 span spa
  • python调用相机和双目相机

    python调用相机 span class token keyword import span cv2 span class token keyword import span numpy span class token keyword
  • 安装PCL1.9.1其它版本号Python3.6+PCL1.9.1+VS2017+gtkbundle_3.6.4版本

    下载 python pcl文件 地址 xff1a https github com strawlab python pcl 安装 VS2017 安装PLC1 91 首先在自己电脑上安装PCL xff08 点击这里 xff09 xff0c 这
  • ROS--机器人小车仿真rviz

    URDF练习 需求描述 创建一个四轮圆柱状机器人模型 xff0c 机器人参数如下 底盘为圆柱状 xff0c 半径 10cm xff0c 高 8cm xff0c 四轮由两个驱动轮和两个万向支撑轮组成 xff0c 两个驱动轮半径为 3 25cm
  • ROS--URDF集成Gazebo仿真小车和rviz结合

    ROS URDF集成Gazebo仿真小车 实现流程 需要编写封装惯性矩阵算法的 xacro 文件 为机器人模型中的每一个 link 添加 collision 和 inertial 标签 xff0c 并且重置颜色属性 在 launch 文件中
  • 使用D435i深度相机运行ORB-SLAM3

    下载安装链接 下载ORB SLAM3地址 xff1a git clone https github com UZ SLAMLab ORB SLAM3 git eigen3多版本安装 xff1a https blog csdn net wei
  • keil5使用一个父工程打开多个子工程文件

    1 首先工程文件需要在同样的文件夹里 2 打开keil5 xff0c 选择Project New Multi Project Workspace 3 将工程文件建立在刚刚的总文件夹里面 xff0c 命名保存 4 弹出此页面 xff08 Cr
  • ​Android动态加载so!这一篇就够了!

    作者 xff1a Pika 链接 xff1a https juejin cn post 7107958280097366030 对于一个普通的android应用来说 xff0c so库的占比通常都是巨高不下的 xff0c 因为我们无可避免的
  • HTTP是什么

    HTTP是什么 HTTP是什么 HTTP协议是Hyper Text Transfer Protocol xff08 超文本传输协议 xff09 的缩写 是用于从万维网 xff08 WWW World Wide Web xff09 服务器传输
  • error: array has incomplete element type ‘char []‘

    原代码 xff1a void explain input char int char a 报错 xff1a error array has incomplete element type 39 char 39 原因 xff1a 可以用二维数
  • STM32串口接收十六进制数转为十进制数(包含负数)

    外部设备传输给STM32单片机十六进制数 例如0x09c4 代表2500 0xff38 代表 200 xff08 并不是65336 xff0c 因为这是有符号的 xff09 串口接收处理函数 接收到 5A A5 06 83 55 00 01
  • 无人机-3无人机ROS应用与开发

    一 ROS是什么 二 为什么要学习ROS 三 怎么学习ROS https www cnblogs com masbay p 10745170 html TF坐标系指机器人在现实世界会有坐标的变换 xff0c ROS已经将其算成固定的程序 x
  • ROS入门-4.安装ROS系统(ubuntu20.04版本安装ros的noetic版本)

    ubuntu20 04版本安装ros的noetic版本 1 添加软件源2 添加密钥3 更新4 安装ROS5 初始化rosdep6 设置环境变量7 测试ROS安装是否成功 1 添加软件源 2 添加密钥 3 更新 4 安装ROS 5 初始化ro
  • 数学建模-12.预测模型

    灰色预测 灰色系统 GM 1 1 模型 xff1a Grey Model GM 1 1 原理介绍 呢么 xff0c 准指数规律的检验 xff1f 发展系数 a 与预测情形的探究 发展系数越小预测的越精确 GM 1 1 模型的评价 在使用GM
  • 数学建模-数学规划模型

    数学规划模型 一 概述 1 什么是数学规划 xff1f 运筹学的一个分支 xff0c 用来研究在给定条件下 即约束条件 xff0c 如何按照某一衡量指标 xff08 目标函数 xff09 来寻求计划 管理工作中的最优方案 即求目标函数在一定
  • 机器学习西瓜书学习记录-第四章 决策树

    第4章 决策树 4 1基本流程 决策树 xff0c 一类常见机器学习方法 xff0c 希望从给定训练集学得一个模型用以对新示例进行分类 一般 xff0c 一棵决策树包含一个根结点 若干个内部结点和若干个叶结点 xff1b 叶结点对应于决策结
  • 机器学习西瓜书学习记录-第五章 神经网络

    第5章 神经网络 5 1神经元模型 神经网络中最基本的成分是神经元模型 M P神经元模型 xff0c 又称 阈值逻辑单元 在模型中 xff0c 神经元接收到来自n个其他神经元传递过来的输入信号 xff0c 这些输入信号通过带权重的连接进行传
  • 机器学习西瓜书学习记录-第六章 支持向量机

    第6章 支持向量机 移步b站学习 学习贴

随机推荐

  • SurfaceFlinger模块

    SurfaceFlinger是一个系统服务 xff0c 作用就是接受不同layer的buffer数据进行合成 xff0c 然后发送到显示设备进行显示 SurfaceFlinger进程是什么时候起来的 xff1f 在之前的Android低版本
  • STM32-串口通信实验

    一 通信接口背景知识 1 通信的两种方式 xff1a 并行通信 传输原理 数据各个位同时传输 优点 速度快缺点 占用引脚资源多 串行通信 传输原理 数据按位顺序传输 优点 占用引脚资源少缺点 速度相对较慢 2 串行通信 按照数据传送的方向
  • UDP介绍,编程流程

    介绍 xff1a 面向无连接的用户数据报协议 xff0c 不需要建立任何连接 xff0c 目的主机接收后不需要确认 UDP特点 xff1a 相比TCP速度快一些简单的应用程序直接使用 不需要加密对于海量数据不采用UDP广播和多播必须采用UD
  • 数据结构-线性表的链式存储(包含代码实现)

    线性表的链式表示和实现 链式存储结构 结点在存储器中的位置是任意的 xff0c 即逻辑上相邻的数据元素在物理上不一定相邻线性表的链式存储结构又称为非顺序映像或链式映像 用一组物理位置任意的存储单元来存放线性表的数据元素这组存储单元既可以是连
  • Android6.0以上高危权限动态申请

    1 在项目的Manifest xml中添加静态权限 拨打电话 lt uses permission android name 61 34 android permission CALL PHONE 34 gt 发送短信 lt uses pe
  • Linux入学—共享文件夹(保姆教程)

    序言 自从上学期上完课以来就没有用过Linux xff0c 最近因为学习传感器数据上传云端的需要 xff0c 安装了Linux xff0c 在开始装jdk的时候需要下载jdk的压缩包 xff0c 需要通过windows上传到Ubuntu 之
  • Ubuntu下安装java环境及idea

    前言 一 JDK的安装 二 配置环境 1 在 系统中配置java环境 三 idea社区版的安装 前言 提示 xff1a 这里可以添加本文要记录的大概内容 xff1a 由于自己的学习需要 xff0c 这里需要用到在Linux系统下的Java
  • stm32f103 光敏传感器BH1750 实现串口回显

    在制作智能花盆的过程中 xff0c 使用了光敏传感器BH1750 因为在网上找了很多都是关于51的 xff0c 32方面的比较少 xff0c 所以这里记录一下BH750的驱动代码 链接 xff1a https pan baidu com s
  • STM32中HAL库使用-串口接收(一)

    1 中断接收 1 1先看中断接收的流程 xff08 以 USART2 为例 xff09 在启动文件中找到中断向量 USART2 IRQHandler 找到 USART2 IRQHandler 的函数定义 可以看到这里又转到另一个函数里去了
  • STM32中HAL库使用-串口发送(二)

    2 中断发送 2 1发送中断的触发流程 由于在STM32中usart2的入口中断只有一个 xff1a 就是上图的中断向量表中红框标出来的 其他的所有中断其实都是从这里出发的 xff0c 我们再和捋接收一样捋一遍发送 首先是USART2 IR
  • Ubuntu20.04下编译安装ORBSLAM2_with_pointcloud_map总结

    与此物大战六个小时 xff0c 终于解决所有问题 xff0c 写此短文记录一下 一 在github上下载源码后 xff0c 解压缩 xff0c 如下 进行g2o with orbslam2的编译 1 报错信息 xff1a ORBSLAM2
  • Android使用ASM修改函数

    目录 参考文章 Android 编译插桩 xff08 一 xff09 xff1a ASM https github com yxhuangCH CSLearn blob master android Android 20 E7 BC 96
  • ORB_SLAM2配置——基于Ubuntu20.04+ROS+gazebo仿真

    一 引言 ORB SLAM2 xff0c 它是基于单目 双目或RGB D相机的一个完整的SLAM系统 xff0c 其中包括地图重用 回环检测和重定位功能 这个系统可以适用于多种环境 xff0c 无论是室内小型手持设备 xff0c 还是工厂环
  • opencv 打开双目摄像头只能采集一个摄像头的问题,及左右目图像分割成两幅图

    一 opencv 打开双目摄像头只能采集一个摄像头的问题 本人采用单USB接口的双目摄像头 xff0c 总是只打开左摄像头的图 xff0c 经摸索后发现主要就是分辨率的问题 xff0c 如果分辨率设置正确 xff0c 便可以打开左右目合成图
  • 基于opencv(c++)和matlab的usb双目相机标定

    本人由于实际需要入手了一款双目免驱usb摄像头 xff0c 因为需要做深度估计 xff0c 故需要标定内参 xff0c 双目相机标定主要是为了获得摄像头的内参 f 1 dx 1 dy cx cy 畸变参数 k1 k2 k3 p1 p1 和外
  • 解决在编译各类改版orbslam时的undefined reference to ****************************问题

    如上面这个问题 xff0c 可以参考这个链接 xff1a 参考链接 参考上面的链接 xff0c 我作出的修改具体为 xff08 1 xff09 移动所缺少的文件 xff08 如本例的libopencv core so 4 2 0 xff09
  • 贝叶斯滤波与卡尔曼滤波(一)

    一 绪论 贝叶斯滤波 xff1a 通过概率统计的方法 xff08 贝叶斯公式 xff09 xff0c 对随机变量进行处理 xff0c 来减小他的不确定度 这里所指的随机变量和教材中所说的变量并不是一回事 xff0c 贝叶斯滤波中所提到的随机
  • 学习ROS-Academy-for-Beginners-noetic,修改记录

    一 编译安装ROS Academy for Beginners noetic 可以参考我之前的博客ROS Academy for Beginers noetic安装教程 之后可以看到里面提供了很多例程 xff0c 包括 软件包 内容 rob
  • STM32的C与汇编语言混合编程

    目录 一 在keil5里面利用C语言调用汇编函数 1 建立新工程 2 编辑代码 C语言代码编辑 xff1a 汇编语言编辑 3 编译调试 二 改写汇编程序 1 C程序改写 2 汇编程序改写 3 编译调试 三 在汇编程序中调用C语言中的函数 一
  • 网络数据传输时的大小端问题

    socket网络字节序以及大端序小端序 不同CPU中 xff0c 4字节整数1在内存空间的存储方式是不同的 4字节整数1可用2进制表示如下 xff1a 00000000 00000000 00000000 00000001 有些CPU以上面