C/C++知識點之詳解C語言的htons函數

摘要:本文主要向大家介紹了C/C++知識點之詳解C語言的htons函數,通過具體的內容向大家展示,希望對大家學習C/C++知識點有所幫助。

本文主要向大家介紹了C/C++知識點之詳解C語言的htons函數,通過具體的內容向大家展示,希望對大家學習C/C++知識點有所幫助。

在Linux和Windows網絡編程時需要用到htons和htonl函數,用來將主機字節順序轉換爲網絡字節順序。

     在Intel機器下,執行以下程序

 

int main()
{
   printf("%d /n",htons(16));

      return 0;
}

得到的結果是4096,初一看感覺很怪。

    解釋如下,數字16的16進製表示爲0x0010,數字4096的16進製表示爲0x1000。 由於Intel機器是小尾端,存儲數字16時實際順序爲1000,存儲4096時實際順序爲0010。因此在發送網絡包時爲了報文中數據爲0010,需要經過htons進行字節轉換。如果用IBM等大尾端機器,則沒有這種字節順序轉換,但爲了程序的可移植性,也最好用這個函數。

   另外用注意,數字所佔位數小於或等於一個字節(8 bits)時,不要用htons轉換。這是因爲對於主機來說,大小尾端的最小單位爲字節(byte)。

什麼是大端模式(big-endian),爲什麼使用大端模式(big-endian)。

uint16_t htons(uint16_t hostshort);
  htons的功能:將一個無符號短整型數值轉換爲網絡字節序,即大端模式(big-endian)
  參數u_short hostshort: 16位無符號整數
  返回值:TCP / IP網絡字節順序
  htons 是把你機器上的整數轉換成“網絡字節序”, 網絡字節序是 big-endian,也就是整數的高位字節存放在內存的低地址處。 而我們常用的 x86 CPU (intel, AMD) 電腦是 little-endian,也就是整數的低位字節放在內存的低字節處。舉個例子吧。假定你的port是0x1234,在網絡字節序裏 這個port放到內存中就應該顯示成addr addr+1,也就是:0x12 0x34;而在x86電腦上,0x1234放到內存中實際是:addr addr+1,也就是:0x34 0x12。htons 的用處就是把實際內存中的整數存放方式調整成“網絡字節序”的方式。

第一個問題:爲什麼使用兩個字節,也就是16位來存儲。

  這個簡單一些,因爲一個字節只能存儲8位2進制數,而計算機的端口數量是65536個,也就是2^16,兩個字節。

第二個爲題:爲什麼計算機需要大端模式和小端模式?

  小端模式 :強制轉換數據不需要調整字節內容,1、2、4字節的存儲方式一樣。
  大端模式 :符號位的判定固定爲第一個字節,容易判斷正負。

    big endian:大尾端,也稱大端(高位)優先存儲。

    little endian:小尾端,也稱小端(低位)優先存儲。

 

   如下00000000 00000000 00000000 00000001的存儲

       

    大尾端: 00000000 00000000 00000000 00000001

           addr+0    addr+1     addr+2   addr+3     //先存高有效位(在低地址)

  

   小尾端: 00000001 00000000 00000000 00000000

           addr+0    addr+1     addr+2   addr+3     //先存低有效位(在低地址)

 

 

 

 

 

   故要判斷機器的體系結構是大尾端還是小尾端,以下程序可以完成任務:

  

   

 

#include <stdio.h>
int main()
{
    int tt = 1;
    char *c = (char*)(&tt);
    if(*c == 1)
    {
        printf("litte endian\n");
    }
    else
    {
        printf("big endian\n");
    }
    return 0;
}

   

 

 

大小尾端數據間的相互轉換

/*
      usage: to convert between the form of big-endian and little-endian
      author: ydzhang
      date: 2008年12月6日20:23:48
*/
#include <stdio.h>
typedef unsigned int u32;
typedef unsigned short u16;

#define BSWAP_16(x) \
        (u16) ( ((((u16)(x) & 0x00ff)) << 8) \
        | (((u16)(x) & 0xff00) >> 8) )

u16 bswap_16(u16 x)
{
    return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8);
}

u32 bswap_32(u32 x)
{
    return ((x & 0x000000ff) << 24) |
           ((x & 0x0000ff00) << 8) |
           ((x & 0x00ff0000) >> 8) |
           ((x & 0xff000000) >> 24);
}

int main()
{
     u16 num_16 = 0x1234;
     u32 num_32 = 0x12345678;

    printf("%x\n", bswap_16(num_16));
    printf("%x\n", BSWAP_16(num_16));
    printf("%x\n", bswap_32(num_32));
    return 0;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章