1. 程式人生 > >Linux網路程式設計(一)基礎

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]$