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

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

生活随笔

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

编程问答

IP地址的三种表示格式 及 在Socket编程中的应用

發(fā)布時(shí)間:2024/4/11 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 IP地址的三种表示格式 及 在Socket编程中的应用 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

關(guān)于windows中的INADDR_ANY這個(gè)宏

頭文件winsock.h中定義#define INADDR_ANY????????????? (u_long)0x00000000

它是用于多IP機(jī)器上???
? 比如你的機(jī)器有三個(gè)ip???
? 192.168.1.1???
? 202.202.202.202???
? 61.1.2.3???
????
? 如果你serv.sin_addr.s_addr=inet_addr("192.168.1.1");???
????
? 然后監(jiān)聽100端口???
????
? 這時(shí)其他機(jī)器只有connect?? 192.168.1.1:100才能成功。???
? connect?? 202.202.202.202:100和connect?? 61.1.2.3:100都會(huì)失敗。???
????
? 如果serv.sin_addr.s_addr = htonl(INADDR_ANY);?? 的話,無(wú)論連接哪個(gè)ip都可以連上的。

?(也可以serv.sin_addr.s_addr = 0;? )

?

獲取到本機(jī)的IP地址,可以通過(guò) getsockname函數(shù)。

===========================================================================================

?

使用TCP/IP協(xié)議進(jìn)行網(wǎng)絡(luò)應(yīng)用開發(fā)的朋友首先要面對(duì)的就是對(duì)IP地址信息的處理。IP地址其實(shí)有三種不同的表示格式:

? ? ???1)Ascii(網(wǎng)絡(luò)點(diǎn)分字符串)-

? ? ? ?2) 網(wǎng)絡(luò)地址(32位無(wú)符號(hào)整形,網(wǎng)絡(luò)字節(jié)序,大頭)

? ? ? ?3)主機(jī)地址 (主機(jī)字節(jié)序) ?

? ? ? ?IP地址是IP網(wǎng)絡(luò)中數(shù)據(jù)傳輸?shù)囊罁?jù),它標(biāo)識(shí)了IP網(wǎng)絡(luò)中的一個(gè)連接,一臺(tái)主機(jī)可以有多個(gè)IP地址,IP分組中的IP地址在網(wǎng)絡(luò)傳輸中將保持不變。下面具體介紹IP地址的三種不同表示格式。

一、點(diǎn)分10進(jìn)制表示格式 ??


? ? ? ? 這是我們最常見的表示格式,比如某機(jī)的IP地址可能為“202.101.105.66”。事實(shí)上,對(duì)于Ipv4(IP版本)來(lái)說(shuō),IP地址是由一個(gè)32位的二進(jìn)制數(shù)所構(gòu)成,但這樣一串?dāng)?shù)字序列無(wú)疑是十分冗長(zhǎng)并且難以閱讀和記憶的。為了方便人們的記憶和使用,就將這串?dāng)?shù)字序列分成4組,每組8位,并改為用 10進(jìn)制數(shù)進(jìn)行表示,最后用小原點(diǎn)隔開,于是就演變成了“點(diǎn)分10進(jìn)制表示格式”。 ??
? ? ? ?來(lái)看看剛才那個(gè)IP地址的具體轉(zhuǎn)化過(guò)程: ??
? ? ?? ?IP實(shí)際地址: 11001010011001010110100101000010 ??
? ? ?? 分成4組后: ? ? 11001010 ? 01100101 ? 01101001 ? 01000010 ??
? ? ?? 十進(jìn)制表示: ?? 202 ? ? ? ? ? ? ? ? ?101 ? ? ? ? ? ? ?105 ? ? ? ? ? ? ? ?66 ??

? ? ??點(diǎn)分表示: ? ? ??202.101.105.66 ??

二、網(wǎng)絡(luò)字節(jié)順序格式(NBO,Network ? Byte ? Order) ?

? ? ? ?網(wǎng)絡(luò)字節(jié)順序格式和主機(jī)字節(jié)順序格式一樣,都只在進(jìn)行網(wǎng)絡(luò)開發(fā)中才會(huì)遇到。因此,在下面的介紹中,我假設(shè)讀者對(duì)Socket編程知識(shí)有一定的基礎(chǔ)。 ??
? ? ? 在網(wǎng)絡(luò)傳輸中,TCP/IP協(xié)議在保存IP地址這個(gè)32位二進(jìn)制數(shù)時(shí), 協(xié)議規(guī)定采用在低位存儲(chǔ)地址中包含數(shù)據(jù)的高位字節(jié)的存儲(chǔ)順序(大頭) ,這種順序格式就被稱為 網(wǎng)絡(luò)字節(jié)順序格式 。在實(shí)際網(wǎng)絡(luò)傳輸時(shí),數(shù)據(jù)按照每32位二進(jìn)制數(shù)為一組進(jìn)行傳輸,由于存儲(chǔ)順序的影響, 實(shí)際的字節(jié)傳輸順序是由高位字節(jié)到低位字節(jié)的傳輸順序 。 ??為了使通信的雙方都能夠理解數(shù)據(jù)分組所攜帶的源地址、目的地址以及分組的長(zhǎng)度等二進(jìn)制信息,無(wú)論是主機(jī)還是路由器,在發(fā)送每一個(gè)分組以前,都必須將二進(jìn)制信息轉(zhuǎn)換為TCP/IP標(biāo)準(zhǔn)的網(wǎng)絡(luò)字節(jié)順序格式。網(wǎng)絡(luò)字節(jié)順序格式的地址不受主機(jī)、路由器類型的影響,它的表示是唯一的。 ??

在Socket編程開發(fā)中,通過(guò)函數(shù)inet_addr和inet_ntoa可以實(shí)現(xiàn)點(diǎn)分字符串與網(wǎng)絡(luò)字節(jié)順序格式IP地址之間的轉(zhuǎn)換。 ??
? inet_addr函數(shù)原型如下: ??
[cpp]?view plaincopyprint?
  • unsigned???long???inet_addr(const???char???FAR???*???cp)?????
  • [cpp]?view plaincopyprint?
  • unsigned???long???inet_addr(const???char???FAR???*???cp)?????
  • ? 函數(shù)中的參數(shù)cp指向網(wǎng)絡(luò)中標(biāo)準(zhǔn)的點(diǎn)分地址字符串,其中每個(gè)以點(diǎn)分開的數(shù)字不可以大于255,這些數(shù)字可以是十進(jìn)制、八進(jìn)制、十六進(jìn)制或者混合使用。如 “10.23.2.3”、“012.003.002.024”、“0xa.0x3.0x14.0x2”、“10.003.2.0x12”。 ??

    ?我們?cè)谇懊娴膕ocket編程提到client端的代碼,連接本地端口:

    [cpp]?view plaincopyprint?
  • /*?File?Name:?client.c?*/????
  • ??
  • #include<stdio.h>???
  • #include<stdlib.h>???
  • #include<string.h>???
  • #include<errno.h>???
  • #include<sys/types.h>???
  • #include<sys/socket.h>???
  • #include<netinet/in.h>???
  • #define?MAXLINE?4096???
  • ??
  • int?main(int?argc,?char**?argv)??
  • {??
  • ????int????sockfd,?n,rec_len;??
  • ????char????recvline[4096],?sendline[4096];??
  • ????char????buf[MAXLINE];??
  • ????struct?sockaddr_in????servaddr;??
  • ??
  • ????if(?(sockfd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0){??
  • ????????printf("create?socket?error:?%s(errno:?%d)\n",?strerror(errno),errno);??
  • ????????exit(0);??
  • ????}??
  • ??
  • ????memset(&servaddr,?0,?sizeof(servaddr));??
  • ????servaddr.sin_family?=?AF_INET;??
  • ????servaddr.sin_port?=?htons(8000);??
  • ????//可以使用:inet_pton(AF_INET,??"127.0.0.1",?servaddr.sin_addr);???
  • ????servaddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");//將字符串形式的IP地址轉(zhuǎn)換為按網(wǎng)絡(luò)字節(jié)順序的整形值???
  • ????connect(sockfd,?(struct?sockaddr*)&servaddr,?sizeof(servaddr))?;??
  • ????printf("send?msg?to?server:?\n");??
  • ????fgets(sendline,?4096,?stdin);??
  • ????send(sockfd,?sendline,?strlen(sendline));??
  • ????irec_len?=?recv(sockfd,?buf,?MAXLINE,0);??
  • ???????
  • ????buf[rec_len]??=?'\0';??
  • ????printf("Received?:?%s?",buf);??
  • ????close(sockfd);??
  • }??
  • [cpp]?view plaincopyprint?
  • /*?File?Name:?client.c?*/????
  • ??
  • #include<stdio.h>??
  • #include<stdlib.h>??
  • #include<string.h>??
  • #include<errno.h>??
  • #include<sys/types.h>??
  • #include<sys/socket.h>??
  • #include<netinet/in.h>??
  • #define?MAXLINE?4096??
  • ??
  • int?main(int?argc,?char**?argv)??
  • {??
  • ????int????sockfd,?n,rec_len;??
  • ????char????recvline[4096],?sendline[4096];??
  • ????char????buf[MAXLINE];??
  • ????struct?sockaddr_in????servaddr;??
  • ??
  • ????if(?(sockfd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0){??
  • ????????printf("create?socket?error:?%s(errno:?%d)\n",?strerror(errno),errno);??
  • ????????exit(0);??
  • ????}??
  • ??
  • ????memset(&servaddr,?0,?sizeof(servaddr));??
  • ????servaddr.sin_family?=?AF_INET;??
  • ????servaddr.sin_port?=?htons(8000);??
  • ????//可以使用:inet_pton(AF_INET,??"127.0.0.1",?servaddr.sin_addr);??
  • ????servaddr.sin_addr.s_addr?=?inet_addr("127.0.0.1");//將字符串形式的IP地址轉(zhuǎn)換為按網(wǎng)絡(luò)字節(jié)順序的整形值??
  • ????connect(sockfd,?(struct?sockaddr*)&servaddr,?sizeof(servaddr))?;??
  • ????printf("send?msg?to?server:?\n");??
  • ????fgets(sendline,?4096,?stdin);??
  • ????send(sockfd,?sendline,?strlen(sendline));??
  • ????irec_len?=?recv(sockfd,?buf,?MAXLINE,0);??
  • ???????
  • ????buf[rec_len]??=?'\0';??
  • ????printf("Received?:?%s?",buf);??
  • ????close(sockfd);??
  • }??
  • ?

    三、主機(jī)字節(jié)順序格式(HBO,Host ? Byte ? Order) ???

    ? ? ? ? 主機(jī)字節(jié)順序格式顧名思義,其IP地址的格式是和具體主機(jī)或者路由器相關(guān)的。對(duì)于不同的主機(jī),在進(jìn)行IP地址的存儲(chǔ)時(shí)有不同的格式,比如對(duì)于 Motorola ? 68k系列主機(jī),其HBO與NBO是相同的。而對(duì)于Intel ? x86系列,HBO與NBO則正好相反。 ??
    ? ? ? ? 在Socket編程中,有四個(gè)函數(shù)來(lái)完成主機(jī)字節(jié)順序格式和網(wǎng)絡(luò)字節(jié)順序格式之間的轉(zhuǎn)換,它們是:htonl、htons、ntohl、和ntohs。 htons和ntohs完成16位無(wú)符號(hào)數(shù)的相互轉(zhuǎn)換,htonl和ntohl完成32位無(wú)符號(hào)數(shù)的相互轉(zhuǎn)換。 ??
    ? ? ? ? 在實(shí)際應(yīng)用中我們常見到將端口號(hào)轉(zhuǎn)換的例子(如上例)。這是因?yàn)?#xff0c;如果用戶輸入一個(gè)數(shù)字,而且將指定使用這一數(shù)字作為端口號(hào),應(yīng)用程序則必須在使用它建立地址以前,把它從主機(jī)字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序(使用htons()函數(shù)),以遵守TCP/IP協(xié)議規(guī)定的存儲(chǔ)標(biāo)準(zhǔn)。相應(yīng)地,如果應(yīng)用程序希望顯示包含于某一地址中的端口號(hào)(例如從getpeername()函數(shù)中返回的),這一端口號(hào)就必須在被顯示前從網(wǎng)絡(luò)順序轉(zhuǎn)換到主機(jī)順序(使用ntohs()函數(shù))。 ??
    ? ? ? ? 那么,對(duì)于IP地址,主機(jī)字節(jié)順序格式的轉(zhuǎn)換又有哪些應(yīng)用呢? ??
    ? ? ? ? 應(yīng)用一,如果想知道從202.156.2.23到202.156.9.65這兩個(gè)IP之間到底有多少個(gè)主機(jī)地址怎么辦?這時(shí)就可以將兩個(gè)IP地址轉(zhuǎn)換為主機(jī)字節(jié)順序的格式然后相減來(lái)得到,具體的實(shí)現(xiàn)如下: ??
    [cpp]?view plaincopyprint?
  • int???GetIPCount(char???*???ip1,char???*???ip2)???{?????
  • ????long???pp;;?????
  • ????long???ss;;?????
  • ??????
  • ????pp???=???ntohl(inet_addr(ip1));;?????
  • ????ss???=???ntohl(inet_addr(ip2));;?????
  • ??????
  • ????return(ss???-???pp???+???1);;?????
  • }???
  • [cpp]?view plaincopyprint?
  • int???GetIPCount(char???*???ip1,char???*???ip2)???{?????
  • ????long???pp;;?????
  • ????long???ss;;?????
  • ??????
  • ????pp???=???ntohl(inet_addr(ip1));;?????
  • ????ss???=???ntohl(inet_addr(ip2));;?????
  • ??????
  • ????return(ss???-???pp???+???1);;?????
  • }???
  • ? ? ? ? 應(yīng)用二,如果對(duì)一個(gè)網(wǎng)段進(jìn)行掃描,比如,當(dāng)前正在掃描202.156.23.255,怎么讓程序知道下一個(gè)應(yīng)掃的IP是202.156.24.0?這時(shí)可以將當(dāng)前IP轉(zhuǎn)換成主機(jī)字節(jié)順序格式并加1后,在轉(zhuǎn)換回網(wǎng)絡(luò)格式
    即可,具體實(shí)現(xiàn)如下: ??
    [cpp]?view plaincopyprint?
  • char???*???GetNextIp(char???*???m_curip)???{?????
  • ??????struct???sockaddr_in???in;;?????
  • ??????long???pp;;?????
  • ??????char???*???re;;?????
  • ????
  • ??????pp???=???ntohl(inet_addr(m_curip));;?????
  • ??????pp???=???pp???+???1;;?????
  • ????
  • ??????in.sin_addr.s_addr???=???htonl(pp);;?????
  • ??????re???=???inet_ntoa(in.sin_addr);;?????
  • ??
  • ??????return???(re);;?????
  • }?????
  • [cpp]?view plaincopyprint?
  • char???*???GetNextIp(char???*???m_curip)???{?????
  • ??????struct???sockaddr_in???in;;?????
  • ??????long???pp;;?????
  • ??????char???*???re;;?????
  • ????
  • ??????pp???=???ntohl(inet_addr(m_curip));;?????
  • ??????pp???=???pp???+???1;;?????
  • ????
  • ??????in.sin_addr.s_addr???=???htonl(pp);;?????
  • ??????re???=???inet_ntoa(in.sin_addr);;?????
  • ??
  • ??????return???(re);;?????
  • }?????

  • ? ? ? 總結(jié) ??

    ? ? ? ?介紹了IP地址的三種不同表示格式,包括各種格式產(chǎn)生的原因、具體含義以及在Socket編程開發(fā)中的一些應(yīng)用。在實(shí)際應(yīng)用中,必須遵循應(yīng)用時(shí)所應(yīng)采用的格式標(biāo)準(zhǔn),同時(shí)還應(yīng)靈活運(yùn)用格式間的相互轉(zhuǎn)換以及計(jì)算技巧。



    字節(jié)序相關(guān)知識(shí)

    ?1)字節(jié)序

    ? ? ? ? ? 字節(jié)序又稱端序,尾序,英文:Endianness。在計(jì)算機(jī)科學(xué)領(lǐng)域中,字節(jié)序是指存放多字節(jié)數(shù)據(jù)的字節(jié)(byte)的順序,典型的情況是整數(shù)在內(nèi)存中的存放方式和網(wǎng)絡(luò)傳輸傳輸順序。Endianness有時(shí)候也可以用指位序(bit)。

    ? ? ? ? 一般而言,字節(jié)序指示了一個(gè)UCS-2字符的哪個(gè)字節(jié)存儲(chǔ)在低地址。如果LSByte 在MSByte的前面,即LSB為低地址,則該字節(jié)序是小端序;反之則是大端序。在網(wǎng)絡(luò)編程中,字節(jié)序是一個(gè)必須被考慮的因素,因?yàn)椴煌奶幚砥黧w系可能采用不同的字節(jié)序。在多平臺(tái)的代碼編程中,字節(jié)序可能會(huì)導(dǎo)致難以察覺的bug。

    名詞:

    最低有效位the least significant bitlsb):是指一個(gè)二進(jìn)制數(shù)字中的第0位(即最低位),具有權(quán)值為2^0,可以用它來(lái)檢測(cè)數(shù)的奇偶性。與之相反的稱之為最高有效位。在大端序中,lsb指最右邊的位。

    最高有效位the Most Significant Bitmsb):是指一個(gè)n位二進(jìn)制數(shù)字中的n-1位,具有最高的權(quán)值。與之相反的稱之為最低有效位。在大端序中,msb即指最左端的位。

    對(duì)于有符號(hào)二進(jìn)制數(shù),負(fù)數(shù)采用反碼或補(bǔ)碼形式,此時(shí)msb用來(lái)表示符號(hào),msb為1表示負(fù)數(shù),0表示正數(shù)。

    單字節(jié)(abyte):大部分處理器以相同的順序處理位元(bit),因此單字節(jié)的存放方法和傳輸方式一般相同。

    多字節(jié):如整數(shù)(32位機(jī)中一般占4字節(jié)),多字節(jié)對(duì)象被存儲(chǔ)為連續(xù)的字節(jié)序列,數(shù)據(jù)的內(nèi)存地址則是該內(nèi)存地址的最小地址。

    如long型數(shù)據(jù)的地址是ox001,?ox002,?ox003,ox004。則該數(shù)據(jù)的內(nèi)存地址是ox001。

    在不同的處理器的存放多字節(jié)數(shù)據(jù)的方式主要有兩種:

    大端序(英文名稱為big endian)指從最高位起存,位數(shù)最大的數(shù)字在最前,即高字節(jié)存于內(nèi)存低地址,低字節(jié)存于內(nèi)存高地址,?從最高有效字節(jié)到最低有效字節(jié)的順序存儲(chǔ)對(duì)象。

    小端序(英文名稱為little endian)指從對(duì)低位起存,位數(shù)最小的數(shù)字在最前。 即低字節(jié)存于內(nèi)存低地址,高字節(jié)存于內(nèi)存高地址,從最低有效字節(jié)到最高有效字節(jié)的順序存儲(chǔ)對(duì)象。

    簡(jiǎn)單打個(gè)比方說(shuō),十進(jìn)制數(shù)12345。1的位數(shù)最高,是萬(wàn)位;5的位數(shù)最低,是個(gè)位。?

    大端序的話,就是從萬(wàn)位開始存,表示為12345;?
    小端序的話,就是從各位開始存,表示為54321.

    再如一個(gè)long型數(shù)據(jù)0x12345678的存儲(chǔ)表示:

    大端序存儲(chǔ)表示:

    ?

    內(nèi)存地址

    數(shù)據(jù)

    內(nèi)存低地址-->????a

    0x001

    12

    a+1

    0x002

    34

    a+2

    0x003

    56

    內(nèi)存高地址-->a+3

    0x004

    78

    小端序的存儲(chǔ)表示:

    ?

    內(nèi)存地址

    數(shù)據(jù)

    內(nèi)存低地址-->a

    0x001

    78

    a+1

    0x002

    56

    a+2

    0x003

    34

    內(nèi)存高地址-->a+3

    0x004

    12


    2)網(wǎng)絡(luò)序

    網(wǎng)絡(luò)傳輸一般采用大端序,也被稱之為網(wǎng)絡(luò)字節(jié)序,或網(wǎng)絡(luò)序IP協(xié)議中定義大端序?yàn)榫W(wǎng)絡(luò)字節(jié)序。

    socketAPI定義了一組轉(zhuǎn)換函數(shù),用于16和32bit整數(shù)在網(wǎng)絡(luò)序和本機(jī)字節(jié)序之間的轉(zhuǎn)換。htonl,htons用于本機(jī)序轉(zhuǎn)換到網(wǎng)絡(luò)序;ntohl,ntohs用于網(wǎng)絡(luò)序轉(zhuǎn)換到本機(jī)序。

    3)位序

    一般用于描述串行設(shè)備的傳輸順序。一般硬件傳輸采用小端序(先傳低位),但I2C協(xié)議采用大端序。網(wǎng)絡(luò)協(xié)議中只有數(shù)據(jù)鏈路層的底端會(huì)涉及到。

    4)處理器體系

    ?1)小端序體系x86MOS Technology 6502Z80VAXPDP-11等處理器為L(zhǎng)ittleendian。

    ?2)大端序體系Motorola 6800Motorola 68000PowerPC 970System/370SPARC(除V9外)等處理器為Big endian

    ?3)可配置:ARM,?PowerPC?(除PowerPC 970外),?DEC Alpha,?SPARCV9,?MIPS,?PA-RISC?and?IA64的字節(jié)序是可配置的。

    5) 編程判斷大端序和小端序

    [cpp]?view plaincopyprint?
  • #include?<stdio.h>???
  • ??
  • bool?IsBigEndian(long?a)??
  • {??
  • ????if(((char?*)&a)[3]?==?1)??
  • ????????return?true?;??
  • ????else??
  • ????????return?false?;??
  • }??
  • ??
  • void?main(){??
  • ????bool?b?;??
  • ????long?a?=?0x12345678;???
  • ????b?=?IsBigEndian(a?);??
  • ????printf("%d",?&a);??
  • }??
  • [cpp]?view plaincopyprint?
  • #include?<stdio.h>??
  • ??
  • bool?IsBigEndian(long?a)??
  • {??
  • ????if(((char?*)&a)[3]?==?1)??
  • ????????return?true?;??
  • ????else??
  • ????????return?false?;??
  • }??
  • ??
  • void?main(){??
  • ????bool?b?;??
  • ????long?a?=?0x12345678;???
  • ????b?=?IsBigEndian(a?);??
  • ????printf("%d",?&a);??
  • }??
  • 打開VS的內(nèi)存窗口,查看內(nèi)存存儲(chǔ)方式:

    設(shè)定斷點(diǎn):


    打開 debug——>window——>Memory

    查看變量a 的地址:0x002BFE50


    查看內(nèi)存地址:

    從上面看出我使用的x86?,是小端序。

    從而驗(yàn)證 b =false是正確的。

    ?

    總結(jié)

    以上是生活随笔為你收集整理的IP地址的三种表示格式 及 在Socket编程中的应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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