-
2021-05-19 08:18:35
函数说明
相关函数:htonl, htons, ntohl
头文件:#include
定义函数:unsigned short int ntohs(unsigned short int netshort);
函数说明:ntohs()用来将参数指定的16 位netshort 转换成主机字符顺序.
返回值:返回对应的主机顺序.
范例:参考getservent().
在C/C++写网络程序的时候,往往会遇到字节的网络顺序和主机顺序的问题。这是就可能用到htons(), ntohl(), ntohs(),htons()这4个函数。
网络字节顺序与本地字节顺序之间的转换函数:
htonl()--"Host to Network Long"
ntohl()--"Network to Host Long"
htons()--"Host to Network Short"
ntohs()--"Network to Host Short"
之所以需要这些函数是因为计算机数据表示存在两种字节顺序:NBO与HBO
网络字节顺序NBO(Network Byte Order):
按从高到低的顺序存储,在网络上使用统一的网络字节顺序,可以避免兼容性问题。
主机字节顺序(HBO,Host Byte Order):
不同的机器HBO不相同,与CPU设计有关,数据的顺序是由cpu决定的,而与操作系统无关。
如 Intel x86结构下,short型数0x1234表示为34 12, int型数0x12345678表示为78 56 34 12
如IBM power PC结构下,short型数0x1234表示为12 34, int型数0x12345678表示为12 34 56 78
由于这个原因不同体系结构的机器之间无法通信,所以要转换成一种约定的数序,也就是网络字节顺序,其实就是如同power pc那样的顺序 。在PC开发中有ntohl和htonl函数可以用来进行网络字节和主机字节的转换。
【网络编程一】主机字节序与网络字节序以及ip地址转换函数
在计算机设计之初,对内存中数据的处理也有不同的方式,(低位数据存储在低位地址处或者高位数据存储在低位地址处),然而,在通信的过程中(ISO/OSI模型和TCP/IP四层模型中),数据被一步步封装(然后 ...
c# 主机和网络字节序的转换 关于网络字节序和主机字节序的转换
最近使用C#进行网络开发,需要处理ISO8583报文,由于其中有些域是数值型的,于是在传输的时候涉及到了字节序的转换. 字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有两种字节顺序, ...
在C语言中基本数据类型所占的字节数
基本数据类型所占的字节数其实跟C语言本身没有太大的关系,它取决于编译器的位数,下面这张表说明了不同编译器下基本数据类型的长度: 32位编译器中各基本类型所占字节数: 注:对于32位的编译器,指针变量的 ...
Java 语言中一个字符占几个字节?
Java中理论说是一个字符(汉字 字母)占用两个字节. 但是在UTF-8的时候 new String("字").getBytes().length 返回的是3 表示3个字节 作者: ...
C语言中几种类型所占字节数
其实C标准并没有具体给出规定哪个基本类型应该是多少个字节数,而且这个也与OS.编译器有关,比如同样是在32位操作系统,VC++的编译器下int类型为4个字节,而在tuborC下则是2个字节. 下面给出 ...
C语言中以文本方式读写文件时换行符转换的注意事项
我们知道在UNIX下是没有回车符(\r)的,只有换行符(\n),而C语言诞生于UNIX(Linux即面向开源的UNIX,Mac OS也是UNIX发展而来的,而Windows是从MS-DOS发展而来,与 ...
浅谈C#语言中的各种数据类型,与数据类型之间的转换
什么是数据类型? 数据类型,百度百科是这样解释的:数据类型在数据结构中的定义是一个值的集合以及定义在这个值集上的一组操作.这样的解释对于一个初学者来说未必太过于深奥. 简单点说,数据类型就是不同长度的 ...
c++和python如何实现主机字节序和网络字节序的相互转换
在上一篇文章网络编程:主机字节序和网络字节序中,介绍了主机字节序和网络字节序的基本概念以及在实际的编程中,何时需要进行网络字节序和主机字节序的转换.本篇文章着重介绍使用c++和python语言,如何实 ...
Python网络编程——主机字节序和网络字节序之间的相互转换
If you ever need to write a low-level network application, it may be necessary to handle the low-lev ...
随机推荐
小Q系列之失恋
这个题其实不难 仔细想想,, 注意题中要求的是一天是12个小时 #include #include #include
BZOJ3236: [Ahoi2013]作业
Description Input Output Sample Input 3 4 1 2 2 1 2 1 3 1 2 1 1 1 3 1 3 2 3 2 3 Sample Output 2 2 1 ...
uva 10051
将每一个分解为六个两面的 简单地dp 回溯输出路径..... #include #include #include
USACO 1.3 Wormholes
Wormholes Farmer John's hobby of conducting high-energy physics experiments on weekends has backfire ...
CentOS的改变系统启动级别
CentOS7改变系统启动级别 systemctl命令: 文本模式:systemctl set-default multi-user.target 图形模式:systemctl set-def ...
QT制作一个图片播放器
前言:使用qt制作了一个简单的图片播放器,可以播放gif.png等格式图片 先来看看播放器的功能(当然是很简陋的,没有很深入的设计): 1.点击图片列表中图片进行播放. 2.自动播放,播放的图片的间隔 ...
bzoj 1875: [SDOI2009]HH去散步
Description HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但 是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又 ...
linu输出重定向
1.tee命令 ls | tee filename #若出现Permission Denied使用下面 ls | sudo tee filename #清空filename后重写 ls | sudo ...
解决Ubuntu自带编译器不好使问题
解决Ubuntu自带编译器不好使问题 1.删除Ubuntu自带的tiny版本,这个版本用起来很别扭不好使. 2.安装full版本的vim 3.显示效果:full版本. 之前自带的版本:
js——作用域和闭包
1. js是编译语言,但是它不是提前编译,编译结果不能在分布式系统中移植.大部分情况下,js的编译发生在代码执行前的几微秒(甚至更短) 2. 一般的编译步骤 分词/词法分析:把字符串分解成词法单元 ...
更多相关内容 -
c++和python如何实现主机字节序和网络字节序的相互转换
2021-01-20 03:33:39在上一篇文章网络编程:主机字节序和网络字节序中,介绍了主机字节序和网络字节序的基本概念以及在实际的编程中,何时需要进行网络字节序和主机字节序的转换。本篇文章着重介绍使用c++和python语言,如何实现主机... -
IP、主机字节序、网络字节序、互转
2017-01-05 11:48:12IP、主机字节序、网络字节序、互转 ------------------------------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using ... -
float字节序高低位转换.txt
2021-11-05 17:07:58float字节序高低位转换.txt -
endian:一个小的golang库,可帮助处理主机到网络和网络到主机的字节序转换
2021-05-01 15:42:04长话短说,每当您需要担心代码是在小型字节序还是大型字节序计算机上运行时,您的方法很可能出错,而应该真正考虑以与字节序无关的方式编写代码就像Rob在他的博客文章中所展示的那样。 在确实需要交换字节的有限... -
高字节序,低字节序讲解
2018-05-14 16:26:24高字节序,低字节序讲解。高字节序,低字节序讲解。高字节序,低字节序讲解 -
基于大端法、小端法以及网络字节序的深入理解
2021-01-20 06:07:48关于字节序(大端法、小端法)的定义《UNXI网络编程》定义:术语“小端”和“大端”表示多字节值的哪一端(小端或大端)存储在该值的起始地址。小端存在起始地址,即是小端字节序;大端存在起始地址,即是大端字节序。 ... -
C语言字节序比特序
2020-07-25 03:19:071、大小端的概念;2、结构体和联合体存储方式;3、位域的概念。 -
浅学字节序——字节序大小端,主机字节序,网络字节序的理解
2017-07-08 23:36:15对字节序的一些理解。 -
【转】网络字节序与主机字节序
2021-03-15 13:55:50最近在项目开发过程中,需要在采用JAVA作为语言的服务器与采用C++作为语言的服务器间进行通信,这就涉及到这两种语言间数据类型的转换以及网络字节序与主机字节序的区别。该文主要说说网络字节序和主机字节序的区别...最近在项目开发过程中,需要在采用JAVA作为语言的服务器与采用C++作为语言的服务器间进行通信,这就涉及到这两种语言间数据类型的转换以及网络字节序与主机字节序的区别。该文主要说说网络字节序和主机字节序的区别以及Little endian与Big endian的概念。其实编程的事就比较简单了
我也懒得写了,直接引用了我觉得写的挺好的两篇文章:
来源:http://blog.ednchina.com/qinyonglyz/194674/message.aspx
1.故事的起源
“endian”这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头(Big-Endian)敲开还是从小头(Little-Endian)敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位。
我们一般将endian翻译成“字节序”,将big endian和little endian称作“大尾”和“小尾”。
2.什么是Big Endian和Little Endian?
在设计计算机系统的时候,有两种处理内存中数据的方法。一种叫为little-endian,存放在内存中最低位的数值是来自数据的最右边部分(也就是数据的最低位部分)。比如一个16进制数字0x12345678,在内存存放的方式如下:
值
0111,1000
0101,0110
0011,0100
0001,0010
地址
100
101
102
103
另一种称为big-endian,正好相反,存放在内存中最低位的数值是来自数据的最左边边部分(也就是数据的最高为部分)。比如一个16进制数字0x12345678,在内存存放的方式如下:
值
0001,0010
0011,0100
0101,0110
0111,1000
地址
100
101
102
103
比如某些文件需要在不同平台处理,或者通过Socket通信。这方面我们可以借助ntohl(), ntohs(), htonl(), and htons()函数进行格式转换。
3.如何判断系统是Big Endian还是Little Endian?
在/usr/include/中(包括子目录)查找字符串BYTE_ORDER(或_BYTE_ORDER, __BYTE_ORDER),确定其值。这个值一般在endian.h或machine/endian.h文件中可以找到,有时在feature.h中,不同的操作系统可能有所不同。一般来说,Little Endian系统BYTE_ORDER(或_BYTE_ORDER,__BYTE_ORDER)为1234,Big Endian系统为4321。大部分用户的操作系统(如windows, FreeBsd,Linux)是Little Endian的。少部分,如MAC OS ,是Big Endian 的。本质上说,Little Endian还是Big Endian与操作系统和芯片类型都有关系。
======================================================================
ext3 文件系统在硬盘分区上的数据是按照 Intel 的 Little-endian 格式存放的,如果是在 PC 以外的平台上开发 ext3 相关的程序,要特别注意这一点。
谈到字节序的问题,必然牵涉到两大 CPU派系。那就是Motorola的PowerPC系列CPU和Intel的x86系列CPU。PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据。那么究竟什么是big endian,什么又是little endian呢?
其实big endian是指低地址存放最高有效字节(MSB),而little endian则是低地址存放最低有效字节(LSB)。
用文字说明可能比较抽象,下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示:Big Endian
低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 12 | 34 | 56 | 78 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+Little Endian 低地址 高地址
----------------------------------------->
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 78 | 56 | 34 | 12 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
从上面两图可以看出,采用big endian方式存储数据是符合我们人类的思维习惯的。而little endian,!@#$%^&*,见鬼去吧 -_-|||
为什么要注意字节序的问题呢?你可能这么问。当然,如果你写的程序只在单机环境下面运行,并且不和别人的程序打交道,那么你完全可以忽略字节序的存在。但是,如果你的程序要跟别人的程序产生交互呢?在这里我想说说两种语言。C/C++语言编写的程序里数据存储顺序是跟编译平台所在的CPU相关的,而 JAVA编写的程序则唯一采用big endian方式来存储数据。试想,如果你用C/C++语言在x86平台下编写的程序跟别人的JAVA程序互通时会产生什么结果?就拿上面的 0x12345678来说,你的程序传递给别人的一个数据,将指向0x12345678的指针传给了JAVA程序,由于JAVA采取big endian方式存储数据,很自然的它会将你的数据翻译为0x78563412。什么?竟然变成另外一个数字了?是的,就是这种后果。因此,在你的C程序传给JAVA程序之前有必要进行字节序的转换工作。
无独有偶,所有网络协议也都是采用big endian的方式来传输数据的。所以有时我们也会把big endian方式称之为网络字节序。当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序后再进行传输。
来源:http://www.cnblogs.com/jacktu/archive/2008/11/24/1339789.html
不同的CPU有不同的字节序类型 这些字节序是指整数在内存中保存的顺序 这个叫做主机序
最常见的有两种
1. Little endian:将低序字节存储在起始地址
2. Big endian:将高序字节存储在起始地址
LE little-endian
最符合人的思维的字节序
地址低位存储值的低位
地址高位存储值的高位
怎么讲是最符合人的思维的字节序,是因为从人的第一观感来说
低位值小,就应该放在内存地址小的地方,也即内存地址低位
反之,高位值就应该放在内存地址大的地方,也即内存地址高位
BE big-endian
最直观的字节序
地址低位存储值的高位
地址高位存储值的低位
为什么说直观,不要考虑对应关系
只需要把内存地址从左到右按照由低到高的顺序写出
把值按照通常的高位到低位的顺序写出
两者对照,一个字节一个字节的填充进去
例子:在内存中双字0x01020304(DWORD)的存储方式
内存地址
4000 4001 4002 4003
LE 04 03 02 01
BE 01 02 03 04
例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
big-endian little-endian
0x0000 0x12 0xcd
0x0001 0x23 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
x86系列CPU都是little-endian的字节序.
网络字节顺序是TCP/IP中规定好的一种数据表示格式,它与具体的CPU类型、操作系统等无关,从而可以保证数据在不同主机之间传输时能够被正确解释。网络字节顺序采用big endian排序方式。
为了进行转换 bsd socket提供了转换的函数 有下面四个
htons 把unsigned short类型从主机序转换到网络序
htonl 把unsigned long类型从主机序转换到网络序
ntohs 把unsigned short类型从网络序转换到主机序
ntohl 把unsigned long类型从网络序转换到主机序
在使用little endian的系统中 这些函数会把字节序进行转换
在使用big endian类型的系统中 这些函数会定义成空宏
同样 在网络程序开发时 或是跨平台开发时 也应该注意保证只用一种字节序 不然两方的解释不一样就会产生bug.
注:
1、网络与主机字节转换函数:htons ntohs htonl ntohl (s 就是short l是long h是host n是network)
2、不同的CPU上运行不同的操作系统,字节序也是不同的,参见下表。
处理器 操作系统 字节排序
Alpha 全部 Little endian
HP-PA NT Little endian
HP-PA UNIX Big endian
Intelx86 全部 Little endian
Motorola680x() 全部 Big endian
MIPS NT Little endian
MIPS UNIX Big endian
PowerPC NT Little endian
PowerPC 非NT Big endian
RS/6000 UNIX Big endian
SPARC UNIX Big endian
IXP1200 ARM核心 全部 Little endian
=============================================
字节序转换类:
/**
* 通信格式转换
*
* Java和一些windows编程语言如c、c++、delphi所写的网络程序进行通讯时,需要进行相应的转换
* 高、低字节之间的转换
* windows的字节序为低字节开头
* linux,unix的字节序为高字节开头
* java则无论平台变化,都是高字节开头
*/
public class FormatTransfer {
/**
* 将int转为低字节在前,高字节在后的byte数组
* @param n int
* @return byte[]
*/
public static byte[] toLH(int n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 将int转为高字节在前,低字节在后的byte数组
* @param n int
* @return byte[]
*/
public static byte[] toHH(int n) {
byte[] b = new byte[4];
b[3] = (byte) (n & 0xff);
b[2] = (byte) (n >> 8 & 0xff);
b[1] = (byte) (n >> 16 & 0xff);
b[0] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 将short转为低字节在前,高字节在后的byte数组
* @param n short
* @return byte[]
*/
public static byte[] toLH(short n) {
byte[] b = new byte[2];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
return b;
}
/**
* 将short转为高字节在前,低字节在后的byte数组
* @param n short
* @return byte[]
*/
public static byte[] toHH(short n) {
byte[] b = new byte[2];
b[1] = (byte) (n & 0xff);
b[0] = (byte) (n >> 8 & 0xff);
return b;
}
/**
* 将将int转为高字节在前,低字节在后的byte数组
public static byte[] toHH(int number) {
int temp = number;
byte[] b = new byte[4];
for (int i = b.length - 1; i > -1; i--) {
b = new Integer(temp & 0xff).byteValue();
temp = temp >> 8;
}
return b;
}
public static byte[] IntToByteArray(int i) {
byte[] abyte0 = new byte[4];
abyte0[3] = (byte) (0xff & i);
abyte0[2] = (byte) ((0xff00 & i) >> 8);
abyte0[1] = (byte) ((0xff0000 & i) >> 16);
abyte0[0] = (byte) ((0xff000000 & i) >> 24);
return abyte0;
}
*/
/**
* 将float转为低字节在前,高字节在后的byte数组
*/
public static byte[] toLH(float f) {
return toLH(Float.floatToRawIntBits(f));
}
/**
* 将float转为高字节在前,低字节在后的byte数组
*/
public static byte[] toHH(float f) {
return toHH(Float.floatToRawIntBits(f));
}
/**
* 将String转为byte数组
*/
public static byte[] stringToBytes(String s, int length) {
while (s.getBytes().length < length) {
s += " ";
}
return s.getBytes();
}
/**
* 将字节数组转换为String
* @param b byte[]
* @return String
*/
public static String bytesToString(byte[] b) {
StringBuffer result = new StringBuffer("");
int length = b.length;
for (int i=0; i
result.append((char)(b & 0xff));
}
return result.toString();
}
/**
* 将字符串转换为byte数组
* @param s String
* @return byte[]
*/
public static byte[] stringToBytes(String s) {
return s.getBytes();
}
/**
* 将高字节数组转换为int
* @param b byte[]
* @return int
*/
public static int hBytesToInt(byte[] b) {
int s = 0;
for (int i = 0; i < 3; i++) {
if (b >= 0) {
s = s + b;
} else {
s = s + 256 + b;
}
s = s * 256;
}
if (b[3] >= 0) {
s = s + b[3];
} else {
s = s + 256 + b[3];
}
return s;
}
/**
* 将低字节数组转换为int
* @param b byte[]
* @return int
*/
public static int lBytesToInt(byte[] b) {
int s = 0;
for (int i = 0; i < 3; i++) {
if (b[3-i] >= 0) {
s = s + b[3-i];
} else {
s = s + 256 + b[3-i];
}
s = s * 256;
}
if (b[0] >= 0) {
s = s + b[0];
} else {
s = s + 256 + b[0];
}
return s;
}
/**
* 高字节数组到short的转换
* @param b byte[]
* @return short
*/
public static short hBytesToShort(byte[] b) {
int s = 0;
if (b[0] >= 0) {
s = s + b[0];
} else {
s = s + 256 + b[0];
}
s = s * 256;
if (b[1] >= 0) {
s = s + b[1];
} else {
s = s + 256 + b[1];
}
short result = (short)s;
return result;
}
/**
* 低字节数组到short的转换
* @param b byte[]
* @return short
*/
public static short lBytesToShort(byte[] b) {
int s = 0;
if (b[1] >= 0) {
s = s + b[1];
} else {
s = s + 256 + b[1];
}
s = s * 256;
if (b[0] >= 0) {
s = s + b[0];
} else {
s = s + 256 + b[0];
}
short result = (short)s;
return result;
}
/**
* 高字节数组转换为float
* @param b byte[]
* @return float
*/
public static float hBytesToFloat(byte[] b) {
int i = 0;
Float F = new Float(0.0);
i = ((((b[0]&0xff)<<8 | (b[1]&0xff))<<8) | (b[2]&0xff))<<8 | (b[3]&0xff);
return F.intBitsToFloat(i);
}
/**
* 低字节数组转换为float
* @param b byte[]
* @return float
*/
public static float lBytesToFloat(byte[] b) {
int i = 0;
Float F = new Float(0.0);
i = ((((b[3]&0xff)<<8 | (b[2]&0xff))<<8) | (b[1]&0xff))<<8 | (b[0]&0xff);
return F.intBitsToFloat(i);
}
/**
* 将byte数组中的元素倒序排列
*/
public static byte[] bytesReverseOrder(byte[] b) {
int length = b.length;
byte[] result = new byte[length];
for(int i=0; i
result[length-i-1] = b;
}
return result;
}
/**
* 打印byte数组
*/
public static void printBytes(byte[] bb) {
int length = bb.length;
for (int i=0; i
System.out.print(bb + " ");
}
System.out.println("");
}
public static void logBytes(byte[] bb) {
int length = bb.length;
String ut = "";
for (int i=0; i
ut = out + bb + " ";
}
}
/**
* 将int类型的值转换为字节序颠倒过来对应的int值
* @param i int
* @return int
*/
public static int reverseInt(int i) {
int result = FormatTransfer.hBytesToInt(FormatTransfer.toLH(i));
return result;
}
/**
* 将short类型的值转换为字节序颠倒过来对应的short值
* @param s short
* @return short
*/
public static short reverseShort(short s) {
short result = FormatTransfer.hBytesToShort(FormatTransfer.toLH(s));
return result;
}
/**
* 将float类型的值转换为字节序颠倒过来对应的float值
* @param f float
* @return float
*/
public static float reverseFloat(float f) {
float result = FormatTransfer.hBytesToFloat(FormatTransfer.toLH(f));
return result;
}
}
-
Linux网络编程——字节序与网络字节序
2021-11-11 19:20:12字节序相关概念 什么是字节序? 字节序是由于不同主处理器(CPU)和操作系统(OS)对多字节的变量在内存中存放顺序的不同而产生的。 字节序的分类?一般分为两类: ①小端字节序(Little Endian,LE...说明:
本文章旨在总结备份、方便以后查询,由于是个人总结,如有不对,欢迎指正;另外,内容大部分来自网络、书籍、和各类手册,如若侵权请告知,马上删帖致歉。
QQ 群 号:513683159 【相互学习】
内容来源:
《Linux网络编程》
内容概述:
简单介绍字节序与网络字节序的概念
两个示例:
1.检查本机字节序
2.字节序转换字节序概念
什么是字节序?
字节序是由于不同主处理器(CPU)和操作系统(OS)对多字节的变量在内存中存放顺序的不同而产生的。
字节序的分类?一般分为两类:
①小端字节序(Little Endian,LE):变量的内存地址起始地址存放低字节,高字节顺序存放
②大端字节序(Big Endian, BE):变量的内存地址起始地址存放高字节,低字节顺序存放
实例:示例:检查本机字节序
源代码:check_order.c
#include <stdio.h> /** * 字节序结构变量 * 联合类型的变量:所有成员占用同一段内存,修改一个成员会影响其他成员。 * 成员value高低端字节可由成员type按字节访问 */ typedef union { unsigned short int value; //短整型变量 unsigned char byte[2]; //字符类型 }to; int main(int argc,char *argv[]) { /** * 变量声明与赋值 * Note: value 和 byte成员共享同一块内存, * 故可通过byte的不同成员访问value的高低字节 */ to typeorder; typeorder.value = 0xabcd; /** * 计算字节序结构中成员字节大小 */ printf("Byte size:value = %ld,byte[0] = %ld\n",sizeof(typeorder.value),sizeof(typeorder.byte[0])); /** * 小端字节序检查 * 小端字节序(LE):起始地址存放低字节,高字节顺序存放 * Note: * 低字节 = byte[1]: 0xab * 高字节 = byte[0]: 0xcd */ if(typeorder.byte[0] == 0xcd && typeorder.byte[1] == 0xab) { printf("Low endian byte order byte[0]:0x%x,byte[1]:0x%x\n", typeorder.byte[0],typeorder.byte[1]); } /** * 大端字节序检查 * 大端字节序(BE):起始地址存放高字节,低字节顺序存放 * Note: * 低字节 = byte[1]: 0xcd * 高字节 = byte[0]: 0xab */ if(typeorder.byte[0] == 0xab && typeorder.byte[1] == 0xcd) { printf("High endian byte order byte[0]:0x%x,byte[1]:0x%x\n", typeorder.byte[0],typeorder.byte[1]); } return 0; }
编译并运行
编译:
执行指令:gcc check_order.c -o check_order
运行:
执行指令:./check_order
结果:Byte size:value = 2,byte[0] = 1 Low endian byte order byte[0]:0xcd,byte[1]:0xab
很明显,我的系统是小端字节序。
网络字节序概念
网络字节序:多字节变量在网络传输时的表示方法,采用的是:高端字节序。
这是由于主机千差万别,故主机字节序不能做到统一,故对于网络传输的变量必须有一个统一的表示方法。
故为程序设计方便,让程序与平台无关,可在网络传输前先对字节序进行转换。字节序转换函数
函数位置:netinet/in.h
主机和网络字节顺序之间转换的函数,如下:
htonl()
–“Host to Network Long” —— 主机字节序到网络字节序的长整型转换
htons()
–“Host to Network Short” ——主机字节序到网络字节序的短整型转换
ntohl()
–“Network to Host Long” —— 网络字节序到主机字节序的长整型转换
ntohs()
–“Network to Host Short” —— 网络字节序到主机字节序的短整型转换
可知,函数命名规则为:字节序 to 字节序 变量类型htonl()函数
函数功能:将主机的无符号长整形数转换成网络字节顺序。
项目 说明 函数原型 extern uint32_t htonl (uint32_t __hostlong) __THROW __attribute__ ((__const__)); 头文件 netinet/in.h 参数说明 __hostlong:主机字节顺序表达的32位数
返回值 返回一个网络字节顺序的值 注意 htons()函数
函数功能:将主机的无符号短整形数转换成网络字节顺序。
项目 说明 函数原型 extern uint16_t htons (uint16_t __hostshort) __THROW __attribute__ ((__const__)); 头文件 netinet/in.h 参数说明 __netshort:主机字节顺序表达的16位数
返回值 返回一个网络字节顺序的值。 注意 ntohl()函数
函数功能:将一个32位数由网络字节顺序转换为主机字节顺序。
项目 说明 函数原型 extern uint32_t ntohl (uint32_t __netlong) __THROW __attribute__ ((__const__)); 头文件 netinet/in.h 参数说明 __netlong:主机字节顺序表达的32位数
返回值 返回一个以主机字节顺序表达的数 注意 ntohs()函数
函数功能:将一个无符号短整形数从网络字节顺序转换为主机字节顺序。
项目 说明 函数原型 extern uint16_t ntohs (uint16_t __netshort) __THROW __attribute__ ((__const__)); 头文件 netinet/in.h 参数说明 __netshort:主机字节顺序表达的16位数
返回值 返回一个以主机字节顺序表达的数 注意 示例:字节序转换
源代码:turn_order.c
#include <stdio.h> #include <netinet/in.h> #define BITS16 16 #define BITS32 32 /** * @union: 16位字节序结构变量 * 联合类型的变量:所有成员占用同一段内存,修改一个成员会影响其他成员。 * 成员value高低端字节可由成员type按字节访问 */ typedef union { unsigned short int value; //16位短整型变量 unsigned char byte[2]; //字符类型 }to16; /** * @union: 32位字节序结构变量 * 联合类型的变量:所有成员占用同一段内存,修改一个成员会影响其他成员。 * 成员value高低端字节可由成员type按字节访问 */ typedef union { unsigned int value; //32位整型变量 unsigned char byte[4]; //字符类型 }to32; /** * @function: 变量值打印函数 * * @description: * 从变量存储空间的第一个字节开始,按照字节打印 * * @param begin: 变量的地址指针 * @param flag : 表示字长的标志变量 * BITS16 :打印16位变量的值 */ void showvalue(unsigned char *begin, int flag) { int num = 0,i = 0; if(flag == BITS16) { num = 2; } else if(flag == BITS32) { num = 4; } for(i = 0;i < num; i++) { printf("%x ",*(begin+i)); } printf("\n"); } int main(int argc,char *argv[]) { /** * 字节序变量定义 */ to16 v16_orig, v16_turn1, v16_turn2; to32 v32_orig, v32_turn1, v32_turn2; /** * 16位变量 */ v16_orig.value = 0xabcd; //原始值赋值 v16_turn1.value = htons(v16_orig.value); //第一次转换的值 v16_turn2.value = htons(v16_turn1.value); //第二次转换的值 /** * 32位变量 */ v32_orig.value = 0x12345678; //原始值赋值 v32_turn1.value = htonl(v32_orig.value); //第一次转换的值 v32_turn2.value = htonl(v32_turn1.value); //第二次转换的值 /** * 16位变量两次字节序转换结果输出: */ printf("16 host to network byte order change:\n"); printf("\t orig:\t"); showvalue(v16_orig.byte,BITS16); //16位数据的原始值 printf("\t 1 times:"); showvalue(v16_turn1.byte,BITS16); //16位数据的第一次转换后的值 printf("\t 2 times:"); showvalue(v16_turn2.byte,BITS16); //16位数据的第二次转换后的值 /** * 32位变量两次字节序转换结果输出: */ printf("32 host to network byte order change:\n"); printf("\t orig:\t"); showvalue(v32_orig.byte,BITS32); //32位数据的原始值 printf("\t 1 times:"); showvalue(v32_turn1.byte,BITS32); //32位数据的第一次转换后的值 printf("\t 2 times:"); showvalue(v32_turn2.byte,BITS32); //32位数据的第二次转换后的值 return 0; }
编译并运行
编译:
执行指令:gcc turn_order.c -o turn_order
运行:
执行指令:./turn_order
结果:16 host to network byte order change: orig: cd ab 1 times:ab cd 2 times:cd ab 32 host to network byte order change: orig: 78 56 34 12 1 times:12 34 56 78 2 times:78 56 34 12
值得注意的是:
上面情形是在小端字节序系统上的结果,会发生改变。
但是在大端字节序系统上,及时调用字节序转换函数也是不会发生改变的。 -
大端字节序与小端字节序 (网络字节序与主机字节序)
2021-12-05 15:49:57大端字节序与小端字节序1. 简介2. 判断机器字节序(C/C++)3. 主机字节序与网络字节序的转换4. IP地址与网络字节序的转换 1. 简介 字节序分为大端字节序(big endian)和...1. 简介
字节序分为大端字节序(big endian)和小端字节序(little endian)。
大端字节序是指一个整数的高位字节(23 ~ 31bit)存储在内存的低地址处,低位字节(0 ~ 7bit)存储在内存的高地址处。(高位在前,低位在后)
小端字节序则是指整数的高位字节存储在内存的高地址位,而低位字节则存储在内存的低地址处。(高位在后,低位在前)因为计算机电路先处理低位字节,效率比较高,计算都是从低位开始的。所以,计算机的内部处理都是小端字节序。所以小端字节序也被称为主机字节序。但是,人类还是习惯读写大端字节序。一般,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。所以大端字节序被称为网络字节序。
举例:0x01234567的两种表示
2. 判断机器字节序(C/C++)
#include <iostream> using namespace std; void byteorder(){ union{ short value; char union_bytes[sizeof(short)]; }test; test.value = 0x0102; if((test.union_bytes[0] == 1) && (test.union_bytes[1] == 2)){ cout << "big endian" << endl; }else if((test.union_bytes[0] == 2) && (test.union_bytes[1] == 1)){ cout << "little endian" << endl; }else{ cout << "unknown..." << endl; } } int main(){ byteorder(); return 0; }
3. 主机字节序与网络字节序的转换
#include <netinet.in.h> unsigned long int htonl(unsigned long int hostlong); unsigned short int htons(unsigned short int hostshort); unsigned long int htonl(unsigned long int netlong); unsigned short int htons(unsigned short int netshort);
- htonl表示“host to network long” ,即将长整型(32bit)的主机字节序转换为网络字节序
- 长整型函数用来转换IP地址,短整型函数用来转换端口号(不限于此)
4. IP地址与网络字节序的转换
#include <arpa/inet.h> int inet_pton(int af,const char* src,void* dst); const char* inet_ntop(int af,const void* src,char* dst,socklen_t cnt);
- inet_pton函数
- 把用字符串表示的IP地址src(点分十进制表示的IPV4,IPV6)转换为网络字节序整数表示的IP地址,并把转换结果存储与dst指向的内存中。
- af表示地址族(AF_INET | AF_INET6)
- 成功返回1,失败返回0并设置errno
- inet_ntop函数
- 进行相反操作,cnt指定目标存储单元的大小
- 成功返回目标存储单元的地址,失败返回NULL,并设置errno
下面两个宏帮助我们指定目标存储单元cnt的大小:
#include <netinet/in.h> #define INET_ADDRSTRLEN 16 #define INET6_ADDRSTRLEN 46
【图片来源】:https://www.cnblogs.com/gremount/p/8830707.html
-
大小端字节序介绍几转换
2017-12-18 14:21:08大小端字节序的介绍和相互转换。在c++中,有4个函数可以实现主机字节序到网络字节序的相互转换。 -
网络字节序和主机字节序
2022-02-13 15:12:50网络字节序说明 TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节。例如上一节的UDP段格式,地址0-1是16位的源端口号,如果这个端口号是1000(0x3e8),则地址0是0x03,地址1是0xe8,也就是先发0x03,... -
主机字节序和网络字节序
2022-05-10 15:38:39字节序 -
大端字节序和小端字节序
2021-08-18 00:21:29大端字节序和小端字节序1.什么是大小端字节序2.验证大小端字节序 1.什么是大小端字节序 计算机硬件有两种储存数据的方式:大端字节序(MSB)和 小端字节序(LSB)。 小端字节序(LSB) 将这样的数据存储在计算机中,... -
计算机网络——网络字节序(大端字节序(Big Endian)\小端字节序(Little Endian))
2020-09-26 08:23:28网络字节序 网络字节序1、网络字节序 (Network Byte Order)和本机转换2、字节序转换函数 网络字节序 1、网络字节序 (Network Byte Order)和本机转换 1、大端、小端字节序 “大端”和”小端”表示多字节值的哪一端... -
字节序、大端字节序(Big Endian)、小端字节序(Little Endian)总结
2021-01-10 10:13:55什么是字节序? 字节序,简单来说,指的是 超过一个字节的数据类型在内存中存储的顺序 有几种字节序? 大端字节序(Big Endian) 高位字节数据存放在内存低地址处,低位字节数据存放在内存高地址处。 小端字节序... -
本地字节序和网络字节序的转换
2021-08-04 21:52:36“端口号”或者“点分十进制的IP”必须先转化为“网络字节序”,才能在网络环境中传输。 TCP/IP 规定,网络数据流采用大端字节序:高地址存低位数据,计算机一般采用小端存储。如下图所示: 因此,从计算机到网络,... -
利用宏将网络字节序和主机字节序ip格式化输出方法
2014-08-28 15:05:54利用宏将网络字节序和主机字节序ip格式化输出为字符串ip -
字节序 主机字节序与网络字节序互相转换
2020-12-05 13:47:43主机字节序与网络字节序互相转换 -
小端字节序与大端字节序
2021-02-28 14:07:08端模式分为:小端字节序和大端字节序,也就是字节在内存中的顺序。小端字节序:低字节存于内存低地址;高字节存于内存高地址。如一个long型数据0x123456780x0029f458 0x780x0029f459 0x560x0029f45a 0x340x0029f... -
c语言主机字节序和网络字节序
2020-11-16 13:48:51一、什么是字节序 字节序是指多字节数据在计算机内存中存储顺序,或者网络传输时各字节的传输顺序,字节序分为大端序和小端序。 大端序:高字节存储在低位地址,传输数据时高位在前; 小端序:高字节存储在高位地址... -
络字节序、地址转换源代码
2015-04-14 19:48:03Linux 网络编程——网络字节序、地址转换,相关教程链接如下: http://blog.csdn.net/tennysonsky/article/details/45045549 -
大端小端字节序,网络字节序,Intel字节序
2022-01-22 13:23:25一、字节序 计算机硬件存储数据有两种方式:大端字节序(big endian)和小端字节序(little endian)。 小端字节序:即低地址存低位字节,或者说在起始地址存放低位字节(Intel的机器都是采用的这种存储方法,因此... -
字节序的理解 大端字节序和小段字节序
2021-03-09 21:32:51字节序的理解 大端字节序和小段字节序 参考: http://www.ruanyifeng.com/blog/2016/11/byte-order.html https://blog.csdn.net/yishengzhiai005/article/details/39672529 一、 计算机硬件有两种储存数据的方式:...