在上一篇文章網絡編程:主機字節序和網絡字節序中,介紹了主機字節序和網絡字節序的基本概念以及在實際的編程中,何時需要進行網絡字節序和主機字節序的轉換。本篇文章着重介紹使用c++和python語言,如何實現主機字節序和網絡字節序的相互轉換。首先回顧一下主機字節序和網絡字節序的概念:
主機字節序就是自己的主機內部,內存中數據的處理方式,要么是大端,要么是小端,取決於處理器類型和操作系統類型,和編程語言無關,如何判斷主機的主機字節序是大端還是小端,請參見網絡編程:主機字節序和網絡字節序第4節中代碼。
網絡字節順序是TCP/IP中規定好的一種數據表示格式,它與具體的CPU類型、操作系統等無關,從而可以保證數據在不同主機之間傳輸時能夠被正確解釋。網絡字節順序采用big endian排序方式。在c++和python中,有4個函數可以實現主機字節序到網絡字節序的相互轉換,如下:
htons: 把unsigned short類型從主機序轉換到網絡序
htonl: 把unsigned long類型從主機序轉換到網絡序
ntohs: 把unsigned short類型從網絡序轉換到主機序
ntohl: 把unsigned long類型從網絡序轉換到主機序
注意:1) 在使用little endian的系統中 這些函數才會把字節序進行轉換 ; 在使用big endian類型的系統中 上述4個函數會定義成空宏,即不會進行任何字節序的任何轉換。
2) 在小端系統中,只有像int、long等多字節類型的數據在網絡傳輸中才需要進行字節序轉換。
接下來,介紹一下在linux和windows平台下c++如何實現字節序轉換以及python語言如何實現字節序轉換。我用的機器是小端字節序。
1.linux + c++ 實現主機字節序和網絡字節序的轉換代碼
1 #include <arpa/inet.h> //1.包含arpa/inet.h 2 #include <stdio.h> 3 int main() 4 { 5 int port=6000; 6 int netPort=htonl(port); 7 printf("netPort=%d\n",netPort); 8 printf("hostPort=%d\n",ntohl(netPort)); 9 return 1; 10 }
output:
netPort=1880555520
hostPort=6000
2.windows + c++ 實現主機字節序和網絡字節序的轉換代碼
1 #include <stdio.h> 2 #include <Winsock2.h> //1.包含<Winsock2.h>, 3 #pragma comment( lib, "ws2_32.lib") //2.引入ws2_32.lib庫 4 void main() 5 { 6 int port=6000; 7 int netPort=htonl(port); 8 printf("netPort=%d\n",netPort); 9 printf("hostPort=%d\n",ntohl(netPort)); 10 }
output:
netPort=1880555520
hostPort=6000
3.python 語言實現主機字節序和網絡字節序的轉換代碼
python語言現在有兩種方法(我所知道的)實現主機字節序和網絡字節序的轉換,一種是通過htons、htonl、ntohl和ntohs等函數實現,另一種是通過struct模塊的pack和unpack函數實現,關於struct模塊的pack和unpack函數的使用方式,請參考我的一篇文章:python中struct.pack()函數和struct.unpack()函數
3.1 htons、htonl、ntohl和ntohs等函數實現字節序轉換
1 #!/usr/bin/python 2 #coding=utf-8 3 import socket 4 port = 6000 5 netPort = socket.htonl(port) 6 hostPort = socket.ntohl(netPort) 7 print"netPort:", netPort 8 print"hostPort:", hostPort
output:
netPort: 1880555520
hostPort: 6000
3.2 struct模塊的pack和unpack函數實現字節序轉換
1 #!/usr/bin/python 2 #coding=utf-8 3 from struct import * 4 port = 6000 5 netPort = pack(">i",port) #等價於htonl(port),只不過pack返回值是字符串類型 6 hostPort = unpack(">i",netPort) 7 print "netPort:",repr(netPort) 8 print "hostPort:",repr(hostPort[0])
output:
netPort: '\x00\x00\x17p'
hostPort: 6000
至此,關於網絡編程中的主機字節序和網絡字節序的相關知識點和內容已接近尾聲,有時間的話會繼續探討一下如何使用c++模擬實現htonl等字節序轉換函數。