Linux网络编程(一)基础

 一、数据存储顺序:大端和小端

        大端模式: 地址的增长顺序与值的增长顺序相反
        小段模式: 地址的增长顺序与值的增长顺序相同

        为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit。但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如果将多个字节安排的问题。

        我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式还是小端模式。所以,主机字节顺序是小端模式。网络字节顺序是大端模式。

        在C语言中,不同于结构体,共用体(联合体)中的几种不同类型的变量存放在同一段内存单元中。利用这一特点,可以用联合体变量判断ARM或X86环境下,存储系统是是大端还是小端模式。

#include "stdio.h"
int main()
{
union w
{
int a; //4 bytes
char b; //1 byte
} c;
c.a=1;
if (c.b==1)
printf("It is Little_endian!\n");
else
printf("It is Big_endian!\n");
return 1;
}
说明:
1 若是小端模式,由低地址到高地址c.a存放为0x01 00 00 00,c.b被赋值为0x01;
————————————————————————————
地址 0x00000000 0x00000001 0x00000002 0x00000003
  c.a 01                  00                00                00
  c.b 01                  
————————————————————————————
2 若是大端模式,由低地址到高地址c.a存放为0x00 00 00 01,c.b被赋值为0x0;
————————————————————————————
地址 0x00000000 0x00000001 0x00000002 0x00000003
  c.a 00                 00                 00                 01
  c.b 00                  
————————————————————————————

字节序的处理

         因为存在大端小端的问题,所以就要进行统一的转换。

         注意字符串是不用转换的,因为一个字符正好占一字节。存储顺序不影响值。而浮点数也不用转换,因为浮点数的读取规则是在cpu中定义的,是一致的。

         转换所用的函数为:

                htons(),htonl();         主机转为网络字节序,s为short , l为long

                ntohs(),ntohl();         网络转为主机字节序。


二、地址格式的转换

        通常情况下,都是用点分十进制(如:202.134.23.145)来表示IP地址。是个字符串。但是程序中处理时用到的是一个二进制的值。所以要进行转换。

        具体的有四个函数:

#include<stdio.h>
#include<stdlib.h>
#include<netinet/in.h>

int main(){
    //ip地址字符串
    char* sa="202.30.45.11";
    //记录ip地址的结构体
    struct in_addr addr,ret;
    //是网络地址类型
    in_addr_t at;
    //将点分十进制字符串转换为32位网络字节序的IP
    at=inet_addr(sa);
    //十六进制输出
    printf("inet_addr:0x%x \n",at);
    //将点分十进制字符串转换为32位主机字节序,与网络字节序应该是反过来的
    printf("inet_network:0x%x \n",inet_network(sa));
    //结构体中记录IP地址的数据成员 
    addr.s_addr=at;
    //网络字节序转换为点分十进制数
    printf("inet_ntoa:%s \n",inet_ntoa(addr));
    //点分十进制数转换为网络字节序,参数为结构体
    inet_aton(sa,&ret);
    printf("inet_aton:0x%x \n",ret.s_addr);
}
运行结果:

[localhost 400]$ ./addr
inet_addr:0xb2d26ca 
inet_network:0xca262d0b 
inet_ntoa:202.30.45.11 
inet_aton:0xb2d26ca 
[localhost 400]$ 

你可能感兴趣的:(Linux网络编程(一)基础)