- 浏览: 66073 次
- 性别:
- 来自: 江苏
文章分类
最新评论
-
donghustone:
楼主好强大!!
resin2.1.17 官方下载地址 -
MultiArrow:
这么说的话好像就只有CentOS没有一个比较强的企业在使用。。 ...
诸多linux,但选一个做服务器
最近在项目开发过程中,需要在采用JAVA作为语言的服务器与采用C++作为语言的服务器间进行通信,这就涉及到这两种语言间数据类型的转换以及网络字节序与主机字节序的区别。该文主要说说网络字节序和主机字节序的区别以及Little endian与Big endian的概念。其实编程的事就比较简单了
我也懒得写了,直接引用了我觉得写的挺好的两篇文章:
什么是Big Endian和Little 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 <-----x86系统是小端字节序系统
Motorola680x() 全部 Big endian
MIPS NT Little endian
MIPS UNIX Big endian
PowerPC NT Little endian
PowerPC 非NT Big endian <-----PPC系统是大端字节序系统
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<length; 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<length; i++) {
result[length-i-1] = b;
}
return result;
}
/**
* 打印byte数组
*/
public static void printBytes(byte[] bb) {
int length = bb.length;
for (int i=0; i<length; 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<length; 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;
}
}
发表评论
-
java的社区网站不是用java写的,俺觉得很讽刺
2010-10-17 14:52 882java的技术社区网站不是用java写的,俺觉得很讽刺~~~ -
用户IP地址的三个属性的区别(HTTP_X_FORWARDED_FOR,HTTP_VIA,REM_addr
2009-10-09 18:06 1509一、没有使用代理服务器的情况: REMOTE_ ... -
【ibatis】动态结果集 类型映射
2009-10-20 10:58 1441ibatis的动态结果使用 java.util.HashMap ... -
jni 中要注意的问题
2009-11-24 15:03 1806JNI 的类型和数据结构 J ... -
ConcurrentHashMap应用注意事项
2010-04-13 09:23 17921、public V get(Object key)不涉及到锁 ... -
【转】在Java与C程序间进行socket通信的讨论
2010-04-15 13:29 11721. 背景 使用socket在Java程序与C程序间进行进 ... -
【转】单例模式不可使用双重检查锁定
2010-04-21 00:49 1131转自:http://www.ibm.com/develope ... -
四个有用的过虑器
2010-04-24 16:36 671一、使浏览器不缓存页面的过滤器 import javax.se ... -
汉字字符编码与转码详解
2010-04-26 14:03 819程序中有汉字参数,经常会遇到编码转码问题,总结下: 1.汉字为 ... -
java dom4j操作xml
2010-05-22 18:26 825java dom4j操作xml SAXReader reade ... -
jni javac++ 参数传递问题解决
2010-05-23 13:18 1229一,问题 1.多参数回传 2.参数传递出现乱码 二,解决 ... -
汉字字符编码与转码详解
2010-05-23 13:19 853程序中有汉字参数,经常会遇到编码转码问题,总结下: 1.汉字为 ...
相关推荐
网络字节序和主机字节序 在计算机科学中,字节序(Endianness)是指整数在内存中保存的顺序。不同的 CPU 有不同的字节序类型,这些字节序是指整数在内存中保存的顺序,这个叫做主机序。 常见的有两种字节序:...
- `htons()`:主机字节序转网络字节序(Host to Network Short) 这些函数可以帮助开发者确保数据在发送前已经被正确地格式化,并且在接收后能够被正确解析。 ### 检测主机大小端类型 在C语言中,可以通过编写...
IP、主机字节序、网络字节序、互转 ------------------------------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net; using ...
利用宏将网络字节序和主机字节序ip格式化输出为字符串ip
网络字节序与主机字节序
网络字节序 主机字节序
在上一篇文章网络编程:主机字节序和网络字节序中,介绍了主机字节序和网络字节序的基本概念以及在实际的编程中,何时需要进行网络字节序和主机字节序的转换。本篇文章着重介绍使用c++和python语言,如何实现主机...
1. `htons()`(Host to Network Short):将主机字节序的短整型(16位)转换为网络字节序。 2. `ntohs()`(Network to Host Short):将网络字节序的短整型转换为主机字节序。 3. `htonl()`(Host to Network Long)...
上述两个示例代码均实现了将一个16位的端口号`6000`从主机字节序转换为网络字节序,然后再将其转回主机字节序的过程。输出结果表明转换过程正确无误。 #### 六、总结 掌握大小端字节序以及网络字节序的相关知识对于...
这其中包括了网络字节顺序(Network Byte Order)与主机字节顺序(Host Byte Order)之间的转换问题。本文将详细介绍这两种字节顺序的概念、区别以及如何进行转换。 #### 一、字节顺序的基本概念 **字节顺序**指的...
需要注意的是,这些函数只对网络字节序与主机字节序不同的平台有效。 - 自定义实现:对于不支持上述函数的环境,可以手动编写转换函数。例如,对于一个32位整数,可以分为4个8位字节,然后按照大端或小端规则重新...
在跨平台的网络编程中,字节序转换函数如htonl(主机到网络字节序,long)、ntohl(网络到主机字节序,long)、htons(主机到网络字节序,short)和ntohs(网络到主机字节序,short)非常常见,它们确保数据在网络上...
网络中表示的IP地址与主机表示不同,本程序通过转换来表示。
例如,`htonl`函数将主机字节序的32位整数转换为网络字节序,`ntohl`则是将网络字节序的32位整数转换回主机字节序。 在实际编程中,我们还需要考虑到字节序问题可能影响到的数据结构,比如结构体(struct)。如果...
尾数 一个小的golang库,可帮助处理主机到网络和网络到主机的字节序转换免责声明在使用此库之前,请阅读并了解Rob Pike的有关的博客文章。 长话短说,每当您需要担心代码是在小型字节序还是大型字节序计算机上运行时...
项目中需要64位数的字节序转换,主机序转换成网路序或者相反转换,写了2个函数,有需要的可以参考。
STM32F103通常是小端字节序,但如果你需要在不同字节序的系统间交换数据,可能需要进行字节序转换,例如使用`ntohl`(网络字节序到主机字节序)和`htonl`(主机字节序到网络字节序)函数。 以上就是关于STM32F103上...
用C语言写的判断主机字节序的代码,一共有2种方法判断
判断主机到底是大端还是小端的c程序!利用位置判断
主机字节序和网络字节序 主机字节序即内存中存储字节的方法有: 1. Little endian:将低序字节存储在起始地址 2. Big endian:将高序字节存储在起始地址 网络字序表示网络协议在处理多字节时的顺序,一律为big ...