字节序

MIPS 大端序和小端序的问题

人走茶凉 提交于 2019-12-06 04:41:33
本文转载自链接: https://blog.csdn.net/Z_hehe/article/details/53310157 果然,继上次移植Libjpeg到openWRT上的问题之后,新的问题又出现了,之前写的用RTP传输jpg图像到VLC的程序,在虚拟机上运行时没问题的,可是在交叉编译到开发板上的时候就不行了,图像数据是传输出去了,但是VLC端就是接收不到图像。最后用抓包工具抓包看了看才发现,抓的包是一团乱啊,在UDP头后面的RTP头数据完全乱套了。抓包还抓到了TCP的三次握手(搞不懂为啥),还有个什么加密什么来着(以为是加密,后来才发现想多了)。 没办法,从程序开始找问题啊,最后发现可能就是字节序的问题。果然,把倒着写的RTP头定义正着写,传输抓包时才能收到正确的RTP的头的设置,图像也能在VLC显示出来。 后来又去网上逛了逛,才发现,大部分的MIPS和网络字节序一样,为大端模式,而我平时在ubuntu的虚拟机和arm开发板上都是小端模式,这就要一个字节序转换函数(htonl,htons,),但是在MIPS上的大端模式就不用了,所以把程序里的字节序转换函数也去掉就行了。 顺便复习下大端序和小端序吧: 字节序,又称端序,尾序,英文:Endianness。 在计算机科学领域中,字节序是指存放多字节数据的字节(byte)的顺序,典型的情况是整数在内存中的存放方式和网络传输的传输顺序

golang Endian字节序

只谈情不闲聊 提交于 2019-12-06 02:51:50
golang 字节序 简述 最近看TCP通信发现字节序,对此不太了解,故记录下来。 所谓字节序就是字符顺序。在查看资料常用的有2类排序方式: Big-Endian 高位字节放在内存的低地址端,低位字节放在内存的高地址端。 Little-Endian 低位字节放在内存的低地址段,高位字节放在内存的高地址端。 例如 十进制数 255 用二进制表示为 1111 1111 ,十进制数 256 用二进制表示则为 1 0000 0000 那么这个1存放的位置是在前还是后,就是 Big-Endian 和 ittle-Endian 的区别 golang中 在golang 中 encoding/binary 提供了二进制序列化的功能。 提供read 读取编码 和write写编码的等方法 func Read(r io.Reader, order ByteOrder, data interface{}) error func Write(w io.Writer, order ByteOrder, data interface{}) error 及一个排序接口 type ByteOrder interface { Uint16([]byte) uint16 Uint32([]byte) uint32 Uint64([]byte) uint64 PutUint16([]byte, uint16)

Java与C++Socket通讯注意

醉酒当歌 提交于 2019-12-04 22:14:56
c++与java进行socket通信时注意事项 因为java发送的都是网络字节序(big-endium),而c++是主机字节序(little-endium),所以当消息中有整型,浮点型(应尽量避免使用)的时候需要用htonl,htons,ntohl,ntohs等函数转换一下,字符串由于是单字节排序的不需要转换,但应注意c++字符串是以'/0'作为结束符的,如果找不到'/0'可能会出现一些乱码,所以接收的时候可以分配一个length+1的buffer用来接收消息. 举例:c++ server, java client,假设开发的是c++ server,那么: java client--------->c++ server: c++ server需要调用ntohs,ntohl c++ server--------->java client: c++ server需要调用htons,htonl 至于浮点型可以使用以下的函数转换: float tcp_htonf(float f) { unsigned char *p, p0, p1; if(htons(1) ==1) return f; p =(unsigned char *)&f; p0 =p[0]; p1 =p[1]; p[0] =p[3]; p[3] =p0; p[1] =p[2]; p[2] =p1; return f; }

大小端字节序

泪湿孤枕 提交于 2019-12-03 14:55:05
现代CPU计算时一次都能装载多个字节(如32位计算机一次装载4字节),多字节的数值在内存中高低位的排列方式会影响所表示的数值,以int32类型的数值169756310(十六进制表示为:0x0103070f;二进制表示为:0b 00000001 00000011 00000111 00001111)为例,在内存中用4个字节存储,4个字节的内容分别是0x01(00000001)、0x03(00000011)、0x07(00000111)、0x0f(00001111)。根据字节高低位排序方式的不同,可以分为:大端字节序(big endian)和 小端字节序(little endian)。 大端字节序 大端字节序是指一个整数的高位字节(如上例中的0x01)存储在内存的低地址处,可以理解为数值的高位部分靠前存储。以前面的0x0103070f为例,假如存储在内存中的起始地址为0x12345678,则0x0103070f在内存中的存储为: 地址0x12345678处存储内容为:0x01(00000001) 地址0x12345679处存储内容为:0x03(00000011) 地址0x1234567a处存储内容为:0x07(00000111) 地址0x1234567b处存储内容为:0x0f(00001111) 小端字节序 和大端字节序相反,小端字节序把数值的低位字节存储在内存的低地址处

ByteBuffer: 图解ByteBuffer(转)

試著忘記壹切 提交于 2019-12-03 02:18:34
ByteBuffer前前后后看过好几次了,实际使用也用了一些,总觉得条理不够清晰。 《程序员的思维修炼》一本书讲过,主动学习,要比单纯看资料效果来的好,所以干脆写个详细点的文章来记录一下。 概述 ByteBuffer是NIO里用得最多的Buffer,它包含两个实现方式: HeapByteBuffer 是基于 Java 堆的实现,而 DirectByteBuffer 则使用了 unsafe 的API进行了堆外的实现。这里只说HeapByteBuffer。 使用 ByteBuffer最核心的方法是 put(byte) 和 get() 。分别是往ByteBuffer里写一个字节,和读一个字节。 值得注意的是,ByteBuffer的读写模式是分开的,正常的应用场景是:往ByteBuffer里写一些数据,然后flip(),然后再读出来。 这里插两个Channel方面的对象,以便更好的理解Buffer。 ReadableByteChannel 是一个从Channel中读取数据,并保存到ByteBuffer的接口,它包含一个方法: public int read(ByteBuffer dst) throws IOException; WritableByteChannel 则是从ByteBuffer中读取数据,并输出到Channel的接口: public int write(ByteBuffer

__attribute__ ((packed))

﹥>﹥吖頭↗ 提交于 2019-12-03 01:53:20
网络通信通常分为基于数据结构的和基于流的。HTTP协议就是后者的一个例子。 有时为了提高程序的处理速度和数据处理的方便,会使用基于数据结构的通信(不需要对流进行解析)。但是,当需要在多平台间进行通信时,基于数据结构的通信,往往要十分注意以下几个方面: [1] 字节序 [2] 变量长度 [3] 内存对齐 在常见的系统架构中(Linux X86,Windows),非单字节长度的变量类型,都是低字节在前,而在某些特定系统中,如Soalris Sparc平台,高字节在前。如果在发送数据前不进行处理,那么由Linux X86发向Soalris Sparc平台的数据值,势必会有极大的偏差,进而程序运行过程中无法出现预计的正常结果,更严重时,会导致段错误。 对于此种情况,我们往往使用同一的字节序。在系统中,有ntohXXX(), htonXXX()等函数,负责将数据在网络字节序和本地字节序之间转换。虽然每种系统的本地字节序不同,但是对于所有系统来说,网络字节序是固定的 -----高字节在前。所以,可以以网络字节序为通信的标准,发送前,数据都转换为网络字节序。 转换的过程,也建议使用ntohXXX(), htonXXX()等标准函数,这样代码可以轻松地在各平台间进行移植(像通信这种很少依赖系统API的代码,做成通用版本是不错的选择)。 变量的长度,在不同的系统之间会有差别,如同是Linux2.6

使用UDP如何进行网络通信

匿名 (未验证) 提交于 2019-12-03 00:30:01
UDP是一种面向无连接的通信协议,何为面向无连接?即两方通信时,另一方可以不在线,但是一方却可以发送消息,期间消息段可能会丢失,但是因为是面向无连接,所以不保证消息一定能送达。 UDP是面向数据报的。但是在通信时,无法保证对方机器和我们的机器的字节序端口什么的都一样,比如有的机器是大端,有的机器是小端,那么报文传输到对方的机器时就会变成混乱的无序的。由于该项问题的产生,所以在网络中对报文进行了规定。 先发出的是低地址,后发出的是高地址,也就是说在网络中采用的是大端字节序。那么在有些小端机器上收到数据之后,要进行转换。在linux的#include<arpa/inet.h>中,定义了转换的函数。 htonl(unit32_t hostlong) htons(unit16_t hostshort) ntohl(unit32_t hostlong) ntohs(unit16_t hostshort) hton-----表示从主机字节序转为网络字节序 ntoh-----表示从网络字节序转为主机字节序 l---表示32位长整数 s ----表示16位长整数 网络中定义了一个结构体sockaddr,为了接收任意类型,这个结构体其中一个参数就是地址类型。 使用其接口我们可以写出基于UDP的服务器和客户端简单的通信程序。 头文件: 服务端: 客户端: 运行结果: 文章来源:

大头小头 字节序

匿名 (未验证) 提交于 2019-12-03 00:22:01
PowerPC系列采用big endian方式存储数据,而x86系列则采用little endian方式存储数据 。那么究竟什么是big endian,什么又是little endian呢? 字节顺序是指占内存多于一个字节类型的数据在内存中的存放顺序,通常有小端、大端两种字节顺序。 小端字节序指低字节数据存放在内存低地址处,高字节数据存放在内存高地址处;大端字节序是高字节数据存放在低地址处,低字节数据存放在高地址处 。 对WORD/DWORD/QWORD等多于1字节类型的数据,在这些嵌入式平台上应该变换其存储顺序。通常我们认为,在空中传输的字节的顺序即网络字节序为标准顺序,考虑到与协议的一致以及与同类其它平台产品的互通,在程序中发数据包时,将主机字节序转换为网络字节序,收数据包处将 网络字节序 转换为主机字节序。 所有网络协议也都是采用big endian的方式来传输数据的。 用文字说明可能比较抽象,下面用图像加以说明。比如数字0x12345678在两种不同字节序CPU中的存储顺序如下所示: 对于0x12345678, Little endian:高地址<------->低:存储数据0x12 0x34 0x56 0x78 判断小端还是大端规则的方法: 另外补充: int x = 1; if(*(char *)&x == 1) //取x指针强制转换为char*类型再取值

socket套接字编程

匿名 (未验证) 提交于 2019-12-02 22:56:40
网络基础概念 IP地址: 在IP协议中用来标识网络中不同主机的地址; IPv4:IP地址是一个4字节,32位的整数; IPv6是一个16字节,128位的整数。 端口号: 用来标识网络中唯一的一个网络服务进程,一个端口号只能被一个进程占用 一个进程可以绑定多个端口号,但是一个端口号只能被一个进程绑定 网络字节序: 发送主机通常将发送缓冲区的数据按内存地址从低到高的顺序发出; 接收主机把从网络上接受的字节依次保存在接收缓冲区中,按内存地址从低到高顺序保存; 所以,网络字节流的地址应该这样规定:先发出的数据是低地址,后发出去的数据是高地址。 TCP/IP协议规定网络数据流应采用大端字节序,即低地址高字节,不管这台主机是大端还是小端,都需要按照TCP/IP规定的网络字节序接受/发送数据。 如果当前主机是小端,需要先将数据转换成大端,否则忽略直接发送。 为提高网络程序的可移植性,使同样的C代码在大端机和小端机上编译后都能正常运行,可以调用库函数做网络字节序和主机字节序之间的转换。 #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

Java字节序

匿名 (未验证) 提交于 2019-12-02 21:40:30
为什么80%的码农都做不了架构师?>>> /** * 通信格式转换 * * 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)