zoukankan      html  css  js  c++  java
  • ios 网络字节顺序的转换HTOS

      最近用socket发送data遇到个问题,字节高地位和服务器不匹配,搞了好久才找到解决的方案,主要用到两个函数HTOL HTOS STOH LTOL 故写此博文

    什么是字节序

    采用维基百科的解释如下:

    在几乎所有的机器上,多字节对象都被存储为连续的字节序列。例如在C语言中,一个类型为int的变量x地址为0x100,那么其对应地址表达式&x的值为0x100。且x的四个字节将被存储在存储器的0x100, 0x101, 0x102, 0x103位置。

    而存储地址内的排列则有两个通用规则。一个多位的整数将按照其存储地址的最低或最高字节排列。如果最低有效字节在最高有效字节的前面,则称小端序;反之则称大端序。在网络应用中,字节序是一个必须被考虑的因素,因为不同机器类型可能采用不同标准的字节序,所以均按照网络标准转化。

    例如假设上述变量x类型为int,位于地址0x100处,它的十六进制为0x01234567,地址范围为0x100~0x103字节,其内部排列顺序依赖于机器的类型。大端法从首位开始将是:0x100: 01, 0x101: 23,..。而小端法将是:0x100: 67, 0x101: 45,..

    相关体系

    • x86,MOS Technology 6502,Z80,VAX,PDP-11等处理器为Little endian。

    • Motorola 6800,Motorola 68000,PowerPC 970,System/370,SPARC(除V9外)等处理器为Big endian

    • ARM, PowerPC (除PowerPC 970外), DEC Alpha, SPARC V9, MIPS, PA-RISC and IA64的字节序是可配置的。

    • 网络传输一般采用大端序,也被称之为网络字节序,或网络序。IP协议中定义大端序为网络字节序。伯克利socket API定义了一组转换函数,用于16和32bit整数在网络序和本机字节序之间的转换。htonl,htons用于本机序转换到网络序;ntohl,ntohs用于网络序转换到本机序。

    -(NSMutableData *)DataForAuthreq
    {
        NSMutableData * senddata = [NSMutableData new];
        NSMutableData * contentdata = [NSMutableData new];
        NSString * uKey = @"nonato";
        NSString * uSecret = @"nonatopassword";
        uint16_t  uklength = 0xff & uKey.length; //strlen(uKey);
        HTONS(uklength);//转换
        [contentdata appendBytes:&uklength  length:sizeof(uklength)];
        [contentdata appendData:[uKey dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO]];
        uint16_t  uSlength = 0xff &  uSecret.length; //strlen(uSecret);
        HTONS(uSlength);//转换
        [contentdata appendBytes:&uSlength  length:sizeof(uSlength)];
        [contentdata appendData:[uSecret dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO]];
      
        uint32_t contentdatalength = 0xffff & (contentdata.length + 4);
        HTONL(contentdatalength);//转换
        [senddata appendBytes:&contentdatalength length:sizeof(4)];
        uint32_t ProtocolId = 0xffff & 0x1002;
        HTONL(ProtocolId);//32字节转换成网络顺序
        [senddata appendBytes:&ProtocolId length:sizeof(4)];
        [senddata appendData:contentdata];
          
        return senddata;
    }
    if (NSHostByteOrder() == NS_LittleEndian) {
            NSLog(@"LittleEndian");
        }
        else if(NSHostByteOrder() == NS_BigEndian){
             NSLog(@"BigEndian");
        }
        else {
             NSLog(@"Unknow");
        }

    通过上述代码打印出来的log,可以知道iOS系统目前采用的是小端序。因此在进行socket网络传输之类的工作时,要记得先把字节序进行转换,然后再传输。iOS自身提供了相应的转换方法,如下:

    1
    2
    3
    
    UInt16  Byte = 0x1234;
    HTONS(Byte);//转换
    NSLog(@"Byte == %x",Byte);//打印出来发现顺序变了
    

    上述代码中 HTONS(x) 是对2字节进行转换,如果要对4字节进行转换,就要用 HTONL(x)进行转换了,要对更高字节,比如8字节(64位)进行转换,就要自己写转换的方法了。

    参考资料

    1. 关于字节序;

    2. Mac&iOS Socket;

    3. 网络字节序与主机字节序 高低位;

    4. 字节序;

    5. Byte Ordering;

  • 相关阅读:
    PDF文件中的Form保存问题
    Understanding IP Fragmentation
    tcp ip guide IPsec IKE
    Windows安全事件日志中的事件编号与描述
    Cisco PIX fix up and Juniper firewall FTP ALG
    很好的IPSec介绍,详细解释了IKE协商的2个阶段的作用
    virtualbox 下运行Ubuntu 8.10的分辨率和guest additions的问题。
    Fixing the ‘Do you want to display nonsecure items’ message
    windows xp 开始菜单里面所有项目右键不起作用。
    HP backup and recovery manager
  • 原文地址:https://www.cnblogs.com/nonato/p/4910339.html
Copyright © 2011-2022 走看看