日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

一文带你秒懂 字节序(byte order),比特序(bit order),位域(bit field)

發(fā)布時(shí)間:2023/12/20 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一文带你秒懂 字节序(byte order),比特序(bit order),位域(bit field) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

字節(jié)序,比特序,位域

  • 前言
  • 引出疑惑
  • 字節(jié)序
  • 比特序
  • 網(wǎng)卡-比特的發(fā)送和接收順序
    • 大端序發(fā)送給小端序
    • 小端序發(fā)送給大端序
  • 位域
  • 定義協(xié)議的萬(wàn)能公式

前言

??不總結(jié)出來(lái)睡不著覺(jué)啊md,本來(lái)想著1點(diǎn)就能寫完,沒(méi)想到3點(diǎn)才寫完

??本文主要介紹比特序在大小端機(jī)器上的排布,以及網(wǎng)卡是如何收發(fā)比特的,文末簡(jiǎn)單介紹了位域的約定。文章主要學(xué)習(xí)與參考字節(jié)序(byte order)和位序(bit order) 和 網(wǎng)絡(luò)字節(jié)序之大小端(字節(jié)序與比特序),這兩篇文章,在其基礎(chǔ)上修正錯(cuò)誤,并繪制新圖。

??本專欄知識(shí)點(diǎn)是通過(guò)零聲教育的線上課學(xué)習(xí),進(jìn)行梳理總結(jié)寫下文章,對(duì)c/c++linux課程感興趣的讀者,可以點(diǎn)擊鏈接 C/C++后臺(tái)高級(jí)服務(wù)器課程介紹 詳細(xì)查看課程的服務(wù)。

引出疑惑

??在網(wǎng)絡(luò)編程中經(jīng)常會(huì)提到網(wǎng)絡(luò)字節(jié)序和主機(jī)序,即網(wǎng)絡(luò)字節(jié)序是大端,主機(jī)序常為小端,所以在接收或者發(fā)送數(shù)據(jù)的時(shí)候常常要進(jìn)行大小端轉(zhuǎn)換。字節(jié)序不再贅述,直接看大端與小端概念、多字節(jié)之間與單字節(jié)多部分的大小端轉(zhuǎn)換詳解(此文看大小端概念和多字節(jié)之間即可,后面的單字節(jié)寫的太垃圾了,還是看本文詳細(xì)的比較好)
??我知道字節(jié)序,大小端我懂,但是當(dāng)我看到websocket的結(jié)構(gòu)體定義,ip頭的結(jié)構(gòu)體定義的時(shí)候,我真的暈了。一個(gè)字節(jié)的8個(gè)bit居然也需要區(qū)分大小端,我真的百思不得其姐,為什么要這樣做
??昨天夜里我一直在想,難道一個(gè)字節(jié)還需要大小端??難道8個(gè)bit的存儲(chǔ)一個(gè)是從左往右,一個(gè)是從右往左??一搜還真是,看了好幾篇文章,但是感覺(jué)看的文章講的都不夠清楚。上面超鏈接里面寫的單字節(jié)多部分大小端其實(shí)寫的不好(因?yàn)閷懙臅r(shí)候還不知道比特序和位域),所以特地寫此文詳細(xì)解釋比特序和位域。

typedef struct _ws_ophdr {unsigned char opcode: 4,rsv3: 1,rsv2: 1,rsv1: 1,fin: 1;unsigned char payload_len: 7,mask: 1; } ws_ophdr;

struct iphdr { #if defined(__LITTLE_ENDIAN_BITFIELD)__u8 ihl:4,version:4; #elif defined (__BIG_ENDIAN_BITFIELD)__u8 version:4,ihl:4; #else #error "Please fix <asm/byteorder.h>" #endif__u8 tos;__be16 tot_len;__be16 id;__be16 frag_off;__u8 ttl;__u8 protocol;__sum16 check;__be32 saddr;__be32 daddr;/*The options start here. */ };

字節(jié)序

??本文的重點(diǎn)不再字節(jié)序之上,但是后續(xù)內(nèi)容是建立在此之上的。如果不懂字節(jié)序的請(qǐng)先看====》大端與小端概念、多字節(jié)之間與單字節(jié)多部分的大小端轉(zhuǎn)換詳解《====看這篇文章的大端與小端概念、多字節(jié)之間內(nèi)容即可,單字節(jié)多部分的大小端轉(zhuǎn)換的原理需要看本文。
??這里我就截一張核心圖放著以方便上下文閱讀了。

比特序

??說(shuō)實(shí)話我都大二開(kāi)學(xué)就大三了,我居然最近才知道比特序這個(gè)名詞,屬實(shí)知識(shí)有點(diǎn)空洞了。那么何謂比特序呢,很好理解,就是一個(gè)字節(jié)內(nèi)的8個(gè)bit之間的順序。

  • 字節(jié)序:多個(gè)字節(jié)的順序,字節(jié)與字節(jié)之間的順序
  • 比特序:一個(gè)字節(jié)內(nèi),多個(gè)bit的順序,bit與bit之間的順序

??在一般情況下,比特序的順序,與字節(jié)序是保持一致的。即如果是小端字節(jié)序,那么高位bit存在高地址,低位bit存在低地址。

??我有一個(gè)很好用的辦法來(lái)區(qū)分大小端,即

  • 從左往右看,如果符合我們的預(yù)期則是大端
  • 從右往左看,如果符合我們的預(yù)期則是小端

??那么問(wèn)題就來(lái)了,既然比特序也區(qū)分大小端,那么下面的主機(jī)序與網(wǎng)絡(luò)序的字節(jié)序轉(zhuǎn)換函數(shù),是否將比特序也一并進(jìn)行轉(zhuǎn)換了呢?

uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);

??就比如上圖的194,用大端讀是194,用小端讀是35,即從左往右看和從右往左看,值是不同的。做了測(cè)試之后發(fā)現(xiàn),上面4個(gè)函數(shù)都沒(méi)有對(duì)比特序做轉(zhuǎn)換。而且寫了這么久的代碼了,也沒(méi)見(jiàn)系統(tǒng)提供比特序轉(zhuǎn)換的函數(shù),這就很奇怪了。
??我小端接收大端的數(shù)據(jù),大端的比特序和小端的順序不一樣,那讀出來(lái)的字面值肯定不一樣啊,咋明明沒(méi)有對(duì)比特序做任何處理,程序安然無(wú)恙呢?

??在我一開(kāi)始接觸字節(jié)序的時(shí)候我就在想會(huì)不會(huì)有比特序這種東西,會(huì)不會(huì)大小端是反的,不知道讀者是否有過(guò)這種思考。

網(wǎng)卡-比特的發(fā)送和接收順序

??既然在程序中無(wú)感知,那么要么是內(nèi)核,要么是網(wǎng)卡硬件幫我們處理了。比特的發(fā)送、接收順序是指一個(gè)字節(jié)中的bit在網(wǎng)絡(luò)電纜中是如何發(fā)送、接收的。在以太網(wǎng)(Ethernet)中,是從最低比特位到最高比特位的發(fā)送順序,也就是最低比特位首先發(fā)送。

??可以看出發(fā)送順序其實(shí)是按照小端序的順序來(lái)發(fā)送的。從圖中我們可以發(fā)現(xiàn),先發(fā)低位bit再發(fā)高位bit,這樣對(duì)于接收方來(lái)說(shuō),無(wú)需知道對(duì)端是大端還是小端,這個(gè)數(shù)據(jù)最左邊一定是低位bit,右邊一定是高位bit。

??牢記這句人能看懂的話: 協(xié)議規(guī)定了先發(fā)送的bit是低位bit,后發(fā)送的是高位bit。那么先接收的一定是低位bit,后接收的一定是高位bit。至于接收之后怎么轉(zhuǎn)換順序,就看主機(jī)是什么端。

??比特的發(fā)送、接收順序?qū)PU、軟件都是不可見(jiàn)的,因?yàn)槲覀兊木W(wǎng)卡會(huì)給我們處理這種轉(zhuǎn)換,在發(fā)送的時(shí)候按照先發(fā)低位bit再發(fā)高位bit的順序發(fā)送比特位,在接收的時(shí)候會(huì)把接收到的比特序轉(zhuǎn),換成主機(jī)的比特序。

??所以按照這一規(guī)定,就能保證在不同的機(jī)器之間進(jìn)行通信不會(huì)發(fā)生前面擔(dān)心的字節(jié)值發(fā)生變化的問(wèn)題。

大端序發(fā)送給小端序

小端序發(fā)送給大端序

位域

??何為位域?就是將一個(gè)字節(jié),分成多個(gè)區(qū)域,如下面結(jié)構(gòu)體所示,一個(gè)字節(jié)8個(gè)bit,被分成了5個(gè)區(qū)域。

??在計(jì)算機(jī)中可尋址的最小單位為字節(jié),bit是無(wú)法尋址的,但是為了抽象我們可以把計(jì)算機(jī)的最小尋址單位變成bit,也就是我們可以單獨(dú)獲得一個(gè)bit位。

??位域有一個(gè)約定:在C語(yǔ)言的結(jié)構(gòu)體中如果包含了位域,如果位域A定義在位域B之前,那么位域A總是出現(xiàn)在低地址的比特位。 這就決定了網(wǎng)絡(luò)編程中位域在定義時(shí)必須處理大小端問(wèn)題。(同樣,結(jié)構(gòu)體中前面的成員也處于較低的地址)

struct bit_order{unsigned char a: 2,b: 3,c: 3; };

??我們發(fā)現(xiàn)大小端序不同的話,abc對(duì)應(yīng)的值也會(huì)不同

unsigned char ch = 121; struct bit_order *ptr = (struct bit_order *)&ch;

定義協(xié)議的萬(wàn)能公式

??一般網(wǎng)絡(luò)協(xié)議都是大端序,大端序低地址存儲(chǔ)高位,所以如果主機(jī)是小端序,則按照協(xié)議規(guī)定反著定義位域即可。因?yàn)榇笮《诵蜣D(zhuǎn)換的話,bit位置就是逆序

??舉個(gè)例子,在websocket的第一個(gè)字節(jié)中,拿FIN舉例,在大端序中它是最低地址0,在小端序中它是最高地址7。

typedef struct _ws_ophdr {unsigned char opcode: 4,rsv3: 1,rsv2: 1,rsv1: 1,fin: 1;unsigned char payload_len: 7,mask: 1; } ws_ophdr;

總結(jié)

以上是生活随笔為你收集整理的一文带你秒懂 字节序(byte order),比特序(bit order),位域(bit field)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。