linux本地序转网络_linux ip转网络字节序 - CSDN
  • 一、字节的概念 字节是指多字节数据的存储顺序,在设计计算机系统的时候,有两种处理内存中数据的方法:大端格式、小端格式。 小端格式(Little-Endian):将低位字节数据存储在低地址。 ...

    一、字节序的概念

    字节序是指多字节数据的存储顺序,在设计计算机系统的时候,有两种处理内存中数据的方法:大端格式、小端格式。


    小端格式(Little-Endian):将低位字节数据存储在低地址。

    大端格式(Big-Endian):将高位字节数据存储在低地址。



    举个简单的例子,对于整形 0x12345678,它在大端格式和小端格式的系统中,分别如下图所示的方式存放:


    下面例子为确定主机的字节序:

    [objc] view plaincopy在CODE上查看代码片派生到我的代码片
    1. #include <stdio.h>  
    2.   
    3. int main(int argc, charchar *argv[])  
    4. {  
    5.     unsigned int a = 0x12345678;  
    6.     unsigned char *p = (unsigned charchar *)&a; //只取一个字节  
    7.     if(0x12 == *p){  
    8.         printf("Big-Endian\n");  
    9.     }else if(0x78 == *p){  
    10.         printf("Little-Endian\n");  
    11.     }  
    12.       
    13.     return 0;  
    14. }  


    网络上的数据流是字节流,对于一个多字节数值,在进行网络传输的时候,先传递哪个字节?也就是说,当接收端收到第一个字节的时候,它是将这个字节作为高位还是低位来处理呢?
     
    网络字节序定义:收到的第一个字节被当作高位看待,这就要求发送端发送的第一个字节应当是高位。而在发送端发送数据时,发送的第一个字节是该数字在内存中起始地址对应的字节。可见多字节数值在发送前,在内存中数值应该以大端法存放。  

    所以,网络协议指定了通讯字节序:大端。只有在多字节数据处理时才需要考虑字节序,运行在同一台计算机上的进程相互通信时,一般不用考虑字节序,异构计算机之间通讯,需要转换自己的字节序为网络字节

    二、字节序转换函数介绍

    以下接口所需头文件:#include <arpa/inet.h>


    uint32_t htonl(uint32_t hostint32);

    功能

    将 32 位主机字节序数据转换成网络字节序数据

    参数

    hostint32:需要转换的 32 位主机字节序数据,uint32_t 为 32 为无符号整型

    返回值

    成功:返回网络字节序的值


    uint16_t htons(uint16_t hostint16);

    功能

    将 16 位主机字节序数据转换成网络字节序数据

    参数

    hostint16:需要转换的 16 位主机字节序数据,uint16_t,unsigned short int

    返回值

    成功:返回网络字节序的值


    测试示例:

    [objc] view plaincopy在CODE上查看代码片派生到我的代码片
    1. #include <stdio.h>  
    2. #include <arpa/inet.h>  
    3.   
    4. int main(int argc, charchar *argv[])  
    5. {  
    6.     int a = 0x01020304;  
    7.     short int b = 0x0102;  
    8.       
    9.     printf("htonl(0x%08x) = 0x%08x\n", a, htonl(a));  
    10.     printf("htons(0x%04x) = 0x%04x\n", b, htons(b));  
    11.       
    12.     return 0;  
    13. }  
    运行结果如下:




    uint32_t ntohl(uint32_t netint32);

    功能

    将 32 位网络字节序数据转换成主机字节序数据

    参数

    netint32:待转换的 32 位网络字节序数据,uint32_t,unsigned int

    返回值

    成功:返回主机字节序的值


    uint16_t ntohs(uint16_t netint16);

    功能

    将 16 位网络字节序数据转换成主机字节序数据

    参数

    netint16:待转换的 16 位网络字节序数据,uint16_t,unsigned short int

    返回值

    成功:返回主机字节序的


    三、地址转换函数
    以下接口所需头文件:#include <arpa/inet.h>

    int inet_pton(int family, const char *strptr, void *addrptr);

    功能

    将点分十进制数串转换成 32 位无符号整数

    参数

    family:协议族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET

    strptr:点分十进制数串

    addrptr:32 位无符号整数的地址

    返回值

    成功返回 1 、 失败返回其它

    测试示例:

    [objc] view plaincopy在CODE上查看代码片派生到我的代码片
    1. #include <stdio.h>  
    2. #include <arpa/inet.h>  
    3. int main()  
    4. {  
    5.     char ip_str[]="172.20.223.75";  
    6.     unsigned int ip_uint = 0;  
    7.     unsigned charchar *ip_p = NULL;  
    8.   
    9.     inet_pton(AF_INET,ip_str,&ip_uint);  
    10.     printf("in_uint = %d\n",ip_uint);  
    11.       
    12.     ip_p = (charchar *)&ip_uint;  
    13.     printf("in_uint = %d,%d,%d,%d\n",*ip_p,*(ip_p+1),*(ip_p+2),*(ip_p+3));  
    14.   
    15.     return 0;  
    16. }  
    运行结果如下:



    const char *inet_ntop( int family, 

    const void *addrptr,   

    char *strptr, 

    size_t len );

    功能

    将 32 位无符号整数转换成点分十进制数串

    参数

    family:协议族( AF_INET、AF_INET6、PF_PACKET 等 ),常用 AF_INET

    addrptr:32 位无符号整数

    strptr:点分十进制数串

    len:strptr 缓存区长度

    len 的宏定义
    #define INET_ADDRSTRLEN   16  // for ipv4

    #define INET6_ADDRSTRLEN  46  // for ipv6

    返回值

    成功:则返回字符串的首地址

    失败:返回 NULL

    测试示例:

    [objc] view plaincopy在CODE上查看代码片派生到我的代码片
    1. #include <stdio.h>  
    2. #include <arpa/inet.h>  
    3. int main()  
    4. {  
    5.     unsigned char ip[] = {172,20,223,75};  
    6.     char ip_str[16] = "NULL";  
    7.   
    8.     inet_ntop(AF_INET,(unsigned intint *)ip,ip_str,16);  
    9.     printf("ip_str = %s\n",ip_str);  
    10.   
    11.     return 0;  
    12. }  
    运行结果如下:



    测试示例代码下载请点此处。

    转自:http://blog.csdn.net/tennysonsky/article/details/45045549

    展开全文
  • #include #include #include #include int main() {  char *str;  struct in_addr inaddr;  int addr = 0x12345678;  inaddr.s_addr=htonl(addr);... printf("转化前本机字节:0x%x%x%x%x\n",*
    #include<stdio.h>
    #include<stdlib.h>
    #include<arpa/inet.h>
    #include<netinet/in.h>
    int main()
    {
        char *str;
        struct in_addr inaddr;
        int addr = 0x12345678;
            inaddr.s_addr=htonl(addr);
        printf("转化前本机字节序:0x%x%x%x%x\n",*((char*)&addr+3),*((char*)&addr+2),*((char*)&addr+1),*((char*)&addr+0));
        str = inet_ntoa(inaddr);
        printf("转化后网络字节序为:%s\n",str);
        return 0;
    }
    展开全文
  • 网络字节本地字节的理解和实现工作中经常用到这两个概念,看了APUE关于大端模式和小端模式的说明,和博文:htonl、ntohl、htons、ntohs函数实现 在这里概括归纳一下,权当备忘。以下所有假设都是在32位x86系统...

    网络字节序和本地字节序的理解和实现

    工作中经常用到这两个概念,看了APUE关于大端模式和小端模式的说明,和博文:htonl、ntohl、htons、ntohs函数实现 在这里概括归纳一下,权当备忘。以下所有假设都是在32位x86系统上。
    大端模式:网络字节序采用的模式,TCP/IP协议栈支持的模式
    小端模式:linux主机采用小端模式存储。

    这里要注意不管是大端还是小端存储,MSB(数据最高字节)始终是在最左边,LSB(数据最低字节)始终是在最右边
    比如以十六进制的0x12345678为例,首先要了解十六进制一位表示4个二进制位,所以这个代表一个32位(8*4),4字节的数据,0x12是MSB,0x78是LSB
    对于大端模式MSB存储在低位字节地址n,LSB存储在高位字节地址n+3,这里的字节地址也是32位的,数据按照地址偏移按单字节存放。
    32整数内部的字节序

    所以要将一个字符指针char* cp强制转换为这个整形地址,由于字节序的不同会带来差异。在小端机器上cp[0]指向最低位地址,存放的是0x78,然而cp[3]指向最高位地址,存放的是0x12;大端反之。
    可以用gdb调试查看,内存内部的变量分布,gdb内存查看命令:
    x /nfu addr
    说明
    x 是 examine 的缩写
    n表示要显示的内存单元的个数
    f表示显示方式, 可取如下值
    x 按十六进制格式显示变量。
    d 按十进制格式显示变量。
    u 按十进制格式显示无符号整型。
    o 按八进制格式显示变量。
    t 按二进制格式显示变量。
    a 按十六进制格式显示变量。
    i 指令地址格式
    c 按字符格式显示变量。
    f 按浮点数格式显示变量。
    u表示一个地址单元的长度
    b表示单字节,
    h表示双字节,
    w表示四字节,
    g表示八字节
    参考博文:gdb查看内存区命令

    小端模式内存查看实验:

    int main(int arc, char* arg[])
    {
        unsingned int a = 0x12345678;
        while(1);
    }
    
    编译:
    编译必须加-g选项才能生成可调试的文件
    gcc littleEnding.c -g -o littleEnding
    
    调试:
    (gdb)gdb ./littleEnding
    (gdb)b 4 //源文件第四行设置断点
    (gdb)r //执行程序
    (gdb)p &a //打印变量地址
    $1 = (unsingned int *)0xbffff543
    (gdb)x 0xbffff543 //查看内存单元内变量
    0xbffff543: 0x12345678
    (gdb) x /4xb 0xbffff543 //单字节查看4个内存单元变量的值
    0xbffff543: 0x78 0x56 0x34 0x12
    (gdb) x /1xb 0xbffff543
    0xbffff543: 0x78
    (gdb) x /2xb 0xbffff543
    0xbffff543: 0x56
    (gdb) x /3xb 0xbffff543
    0xbffff543: 0x34
    (gdb) x /4xb 0xbffff543
    0xbffff543: 0x78 0x56 0x34 0x12
    //可以看到内存最低地址单元存放的是数据的LSB 0x78
    //显然linux x86下是小端的存放方式
    typedef unsigned short int uint16;
    
    typedef unsigned long int uint32;
    
    
    
    // 短整型大小端互换
    
    #define BigLittleSwap16(A)  ((((uint16)(A) & 0xff00) >> 8) | \
    
                                (((uint16)(A) & 0x00ff) << 8))
    
     // 长整型大小端互换
    
    
    
    #define BigLittleSwap32(A)  ((((uint32)(A) & 0xff000000) >> 24) | \
    
                                (((uint32)(A) & 0x00ff0000) >> 8) | \
    
                                (((uint32)(A) & 0x0000ff00) << 8) | \
    
                                (((uint32)(A) & 0x000000ff) << 24))
    
    
    
    
     // 本机大端返回1,小端返回0
    
    int checkCPUendian()
    
    {
    
           union{
    
                  unsigned long int i;
    
                  unsigned char s[4];
    
           }c;
    
    
    
           c.i = 0x12345678;
    //利用了联合的内存分配规则,共享内存仅分配一种数据结构
           return (0x12 == c.s[0]);
    
    }
    
    
    
    // 模拟htonl函数,本机字节序转网络字节序
    
    unsigned long int t_htonl(unsigned long int h)
    
    {
    
           // 若本机为大端,与网络字节序同,直接返回
    
           // 若本机为小端,转换成大端再返回
    
           return checkCPUendian() ? h : BigLittleSwap32(h);
    
    }
    
    
    
    // 模拟ntohl函数,网络字节序转本机字节序
    
    unsigned long int t_ntohl(unsigned long int n)
    
    {
    
           // 若本机为大端,与网络字节序同,直接返回
    
           // 若本机为小端,网络数据转换成小端再返回
    
           return checkCPUendian() ? n : BigLittleSwap32(n);
    
    }
    
    
    
    // 模拟htons函数,本机字节序转网络字节序
    
    unsigned short int t_htons(unsigned short int h)
    
    {
    
           // 若本机为大端,与网络字节序同,直接返回
    
           // 若本机为小端,转换成大端再返回
    
           return checkCPUendian() ? h : BigLittleSwap16(h);
    
    }
    
    
    
    // 模拟ntohs函数,网络字节序转本机字节序
    
    unsigned short int t_ntohs(unsigned short int n)
    
    {
    
           // 若本机为大端,与网络字节序同,直接返回
    
           // 若本机为小端,网络数据转换成小端再返回
    
           return checkCPUendian() ? n : BigLittleSwap16(n);
    
    }
    展开全文
  • 常用于绑定之前地址结构体的设置,将本机端口转为网络字节。 (4)ntohs ,h=host,n=network.常用于与对方通信后,在需要使用对方端口的时候,将其中(收到的对方端口为网络字节)转为主机字节。 (5)inet_...

    (1)inet_addr :转换字符串到地址

    (2)inet_ntoa  转换地址到字符串

    (3)htons  ,h=host,n=network,s = short 。常用于绑定之前地址结构体的设置,将本机端口转为网络字节序。

    (4)ntohs ,h=host,n=network,s = short。 常用于与对方通信后,在需要使用对方端口的时候,将其中(收到的对方端口为网络字节序)转为主机字节序。

    (5)inet_pton, p=pointer n=network。功能同(1),该函数只在linux下有效,winsock无此函数。

    (6)inet_ntop ,p=pointer n=network。功能同(2),该函数只在linux下有效,winsock无此函数。

    (7)htonl,将unsigned long 数据从主机序转为网络序列。(用于格式化本机数据,在网络中传输

    (8) ntohl,将unsigned long 数据从网络序转为主机序列。(用于将网络中接收到的数据转化为本地可识别的整数


    示例:

    (1)和(3)

    struct sockaddr_in serv_addr;
    
    serv_addr.sin_family=AF_INET;
    
    serv_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
    
    serv_addr.sin_port=htons(5000);

    (2)和(4),假设此时cli_addr结构体已通过accept填充。

    struct sockaddr_in cli_addr;
    
    puts(inet_ntoa(cli_addr.sin_addr));
    
    printf("%d\n" ,ntohs(cli_addr.sin_port));

    (5)和(6)

      struct in_addr s;
    
      inet_pton(AF_INET, "127.0.0.1", (void *)&s);
    
      printf("inet_pton: 0x%x\n", s.s_addr);
    
      char addr_str[16]={0x00};
    
      inet_ntop(AF_INET, (void *)&s, addr_str, 16);
    
     
    
    
    


    展开全文
  • 主机字节网络字节的转换过程
  • 文献参考: http://roclinux.cn/?p=1160 一、IP地址的表示法: 1、ASCII表示法: 210.25.132.181,也就是字符串形式,英语叫做IPv4 numbers-and-dots notation。 ...二、
  • Part 1: htons函数具体解释 ... 在Linux和Windows网络编程时需要用到htons和htonl函数,用来将主机字节顺序转换为网络字节顺序。  在Intel机器下,执行以下程序 int main() ...{  
  • 最近在看《linux高性能服务器编程》,在此做个日记,以激励自己,同时分享于有需要的朋友。  现代CPU的累加器一次能装载至少4字节(32位),即一个整数。那么这4字节在内存中排列的顺序将影响它被累加器装载成的...
  •  在进行网络编程的时候,经常会涉及到字节的转换问题(关于字节的概念在这略过)  在系统中为我们实现了这些转换的函数,如ntohs、htons等。   自己尝试着实现这些函数:  首先要...
  • 15.2.10 主机字节网络字节 当在基于intel处理器的linux机器上运行新版本的服务器和客户程序时,可以用netstat命令查看网络连接状况.它显示了客户/服务器连接正在等待关闭.连接将在一段超时间之后关闭,如下所...
  • 最近,需要将一套linux开发程序移植到另外一块开发板上,程序中涉及到了网络通信,且所用开发板的处理器为大端模式,之前为小端模式,因此在数据传输的过程中需要考虑到大小端转换的问题。 全新的界面设计 ,将会...
  • 自:... 在Linux和Windows网络编程时需要用到htons和htonl函数,用来将主机字节顺序转换为网络字节顺序。 在Intel机器下,执行以下程序 int main() { printf("%...
  • float网络字节转换及其逆转换  对于整形已经有了这几个函数htons() 、htonl()、ntohl()、ntohs() 对网络字节进行转换,我这里给出两种对于float型的转换方法: 首先不能简单地通过检查一个值的位来判断它的类型...
  • unsigned long long ntohll(unsigned long long val)  {  if (__BYTE_ORDER == __LITTLE_ENDIAN)  {  return (((unsigned long long )htonl((int)((val > 32))) > 32));  }  else i
  • linux 网络字节

    2013-04-03 20:11:12
    一、大端、小端和网络字节 小端字节:little-endian,将低字节存放在内存的起始地址; 大端字节:big-endian,将高字节存放在内存的其实地址。 例如,数字index=0x11223344,在大小端字节方式下其存储...
  • Linux 网络之IP转换

    2015-06-15 15:45:02
    其中每一个十进制数代表一个字节的无符号数值(按照网络字节)因为每个字节都是无符号的8位数值,这就限制了每一个字节所能表示的范围是0~255。 特殊的IP 每一个字节都为0的地址("0.0.0.0")对应于当前主机;IP...
  • 1、本地字节  由于不同的计算机系统采用不同的字节存储数据,同样一个4字节的32位整数,在内存中存储的方式就不同。 字节分为小尾字节/小端字节(Little Endian)和大尾字节/大端字节(Big Endian)。  ...
  • 网络传输数据要不要转换大小端字节的问题? (2009-1-4 21:29) 我看到书上讲网络时都是说:Internet上的数据以大端方式在网络上传输,所以对于内部是小端方式储存数据的机器,在internet上传输数据时就需要进行...
1 2 3 4 5 ... 20
收藏数 18,756
精华内容 7,502
关键字:

linux本地序转网络