大小字節序的深刻理解和鑑定系統字節序方法

        最近在項目中的soket通訊時,遇到了大小字節序問題和網絡傳輸時的字節序問題,如今給你們整理一下,但願你們對字節序有個比較深刻的瞭解,其實理解了就很簡單的。java

 開始遇到的問題:

      一、本地的數據經過網絡傳輸而後在目的地解析網絡上的數據,字節序是如何統一的linux

      二、字節序不一樣,數據(如0xFF00)存入內存地址中位置不一樣(大字節序:FF--低地址位   00--高地址位  ;小字節序: 00--低地址位  FF--高地址位),爲何讀出的值都是0xFF00ios

下面讓咱們帶着問題來理解:

         大字節序:大端有效 ,高位數據先放入低地址內存  , 低位數據放入高地址內存windows

        小字節序:小端有效,低位數據先放入低地址內存 , 高位數據再放入高地址內存       數組

        注意:描述的是將數據(肉眼看到的)放入內存中的地址(計算機的硬盤內存中)網絡

        而後看一下圖示吧:函數

    相信你們對遇到的第二個問題已經知道結果了吧,如今再來看看第一個問題。ui

        網絡字節序:是大字節序,在把數據進行網絡傳輸時,要保證本身傳輸到網絡上的數據時大字節序。this

       再來看看圖示吧:spa

    1號線路:發數據和接收數據都不須要轉序,由於本身是和網絡都是大字節序

    2號線路:發數據和接收數據須要轉序,由於本身是小字節序,網絡都是大字節序,才能保證本身本系統的數據永遠都是小字節序。可能高級語言(java、C#屏蔽了字節序,你們感覺不到,那是由於高級語言內存進行封裝和處理了)。

    補充一下:若是發端和收端都是小字節序,能夠不轉序,可是這樣作可擴展不高,若是收端是大字節序的話,人家默認爲發過來的數據都是網絡字節序(大字節序),這樣處理就很混亂了。

    好了,如今你們對第一個問題也清楚了吧。

鑑定大小字節序的C/C++語言程序

最後讓咱們來看看鑑定大小字節序的C/C++語言程序吧

#include <stdlib.h>
#include <string.h>

int main()
{
	/*將結合體的整型值賦值爲1,若是是小字節序,小端有效,低地址寫入的就是1,讀出字符ch就是1 
			若是是大字節序,大端有效,低地址寫入的就是0,讀出字符ch就是0*/
	data.i = 1;
	if(data.ch)
	{
		printf("this system is  small-endian\n");	
	} 
	else
	{
		printf("this system is  big-endian\n");		
	}
	
	return 0;
}

    緣由:將結合體的整型值賦值爲1,若是是小字節序,小端有效,低地址寫入的就是1,讀出字符ch就是1 

                                若是是大字節序,大端有效,低地址寫入的就是0,讀出字符ch就是0

    檢驗大小字節序的方法不少,本人認爲這個方法比較簡單,容易理解。

字節序轉化函數htons、htonl、ntohs、ntohl應用

    重要>>>字節序轉化,只是針對二字節、四字節的數據類型,對於單字節和數據區(本質也是單字節的數組)不須要轉化

    注意:在使用轉序函數時,函數內部會去判斷本機字節序,決定要不要轉

#include <iostream>
using namespace std;
/*windows下的頭文件;linux下是#include <arpa/inet.h>*/
#include<Winsock2.h>

int main(int argc,char *argv[])
{
	/*經常使用方法(注意,在使用轉序函數時,內部會去判斷本機字節序,決定要不要轉)
	****** host(本地)-->net(網絡):
	uint32_t htonl(uint32_t hostlong);
	uint16_t htons(uint16_t hostshort);

	****** net(網絡) -->host(本地):
	uint32_t ntohl(uint32_t netlong);
	uint16_t ntohs(uint16_t netshort);
	*/
	unsigned int srcNum = 0xff;
	unsigned int netNum  = htonl(srcNum);
	printf("src-->net: srcNum=0x%x  netNum=0x%x\n",srcNum,netNum);

	unsigned int toNum = ntohl(netNum);
	printf("net-->to : netNum=0x%x  srcNum=0x%x  \n",netNum,toNum);

	system("pause");
	return 0;
}

 此代碼是在windows環境下編譯,若是編譯報錯error LNK2019: 沒法解析的外部符號 _ntohl@4,緣由是沒有引入ws2_32.lib庫,只要在 項目->屬性->配置屬性->連接器->輸入 而後在附件依賴項添加ws2_32.lib 

鞏固練習--IP的存放

一、 IP(無符號整型,如0x80702101)在大、小字節序的系統中的內存是怎麼存放的(把這個IP當作4字節的數組unsigned char arry[4],則數組中每一個元素各是多少呢?)提示:數組的下標越大,地址就越大。

小字節:arr[0]=0x01      arr[1]=0x21      arr[2]=0x70    arr[4]=0x80

大字節:arr[0]=0x80      arr[1]=0x70      arr[2]=0x21    arr[4]=0x01

最後但願能對你們有幫助,有什麼問題請留言,謝謝。

相關文章
相關標籤/搜索