Python IP地址 socket.inet_ntoa unpack/pack

23 if __name__ == '__main__':
 24     netIp=socket.inet_aton('255.255.255.0')
 25     intIp=struct.unpack("!I",netIp)[0]
 26     intIp2=struct.unpack("I",netIp)[0]
 27     print intIp,intIp2
 28     print socket.inet_ntoa(struct.pack("!I",intIp))
 29     print socket.inet_ntoa(struct.pack("I",intIp2))
 30     hostIp=socket.ntohl(intIp)
 31     print hostIp
 python

4294967040 16777215
255.255.255.0
255.255.255.0
16777215mysql

def Ip2Int(ip):linux

    import struct,socket

    return struct.unpack("!I",socket.inet_aton(ip))[0]

此函數從’192.168.1.235’ 能夠轉換爲數字’ 3120670912’,此數字爲網絡字節序sql

def Int2Ip(i):

    import socket,struct

    return socket.inet_ntoa(struct.pack("!I",i))windows

  此函數從網絡字節序的數字’’轉換爲ip網絡

 

>>>
socket.inet_ntoa(struct.pack('I',socket.htonl(16909060)))
'1.2.3.4'

/>>> socket.ntohl(struct.unpack("I",socket.inet_aton('1.2.3.4'))[0])
16909060


再加幾個:
>>> struct.unpack("I",socket.inet_aton('1.2.3.4'))  
(67305985L,)

>>> socket.ntohl(67305985)
16909060

/>>> socket.htonl(16909060)
67305985

/>>> struct.unpack('i',socket.inet_aton('1.2.3.4'))
(67305985,)

/>>> struct.pack('i',16909060)  
'\x04\x03\x02\x01'

/>>> struct.pack('i',67305985)
'\x01\x02\x03\x04'

/>>> socket.inet_ntoa(struct.pack('I',socket.ntohl(16909060)))    
'1.2.3.4'

/>>> socket.htonl(struct.unpack("I",socket.inet_aton('1.2.3.4'))[0])
16909060
socket


1). inet_aton 將ip地址的4段地址分別進行2進制轉化,輸出用16進製表示:
1.2.3.4 ——inet_aton——> 0000 0001,0000 0010,0000 0011,0000 0100

(2).unpack的處理是按16進制(4bit)將2進制字符,從後向前讀入的,低位入,處理成:
00000100 00000011 00000010 00000001 
也就是
 4 3 2 1 

pack也同樣,從後向前讀入字符,因此——
用16進製表示的1 2 3 4(16909060)打包成 4 3 2 1 的順序;
用16進製表示的4 3 2 1(67305985)打包成 1 2 3 4 的順序;

(3) ntohl, htonl 表示的是網絡地址和主機地址之間的轉換(network byte <==> host byte)
因爲unpack/pack的解/打包的顛倒順序,必須經過htonl 或者 ntohl 進行處理。

(4) network byte, host byte
這 2個名詞折騰半天,host byte 因爲處理器的方式不一樣
little-endian或者big-endian,將ip地址轉換的最終輸出是不同的,函數

big-endian: 最高位在左邊(內存存儲空間的最低位)
little-endian: 最高位在右邊(內存存儲空間的最低位).net

 

因爲x86自己的處理屬於little-endian,因此上述應該按照標準的network
byte 進行處理,這樣可避免cpu形成的不一樣:

socket.htonl(struct.unpack("I",socket.inet_aton('1.2.3.4'))[0])

socket.inet_ntoa(struct.pack('I',socket.htonl(16909060)))


###############################################################################

(1個64位amd+32位windows, 1個32位intel+Linux
出來的數值是同樣的:

/>>>
socket.ntohl(struct.unpack("I",socket.inet_aton('220.194.61.32'))[0])
-591250144

/>>> socket.inet_ntoa(struct.pack('I',socket.htonl(-591250144)))
'220.194.61.32'

可是64位amd+64位linux,是這樣:
/>>> socket.ntohl(struct.unpack("I",socket.inet_aton('220.194.61.32'))[0])
3703717152

/>>> socket.inet_ntoa(struct.pack('I',socket.htonl(-591250144)))
'220.194.61.32'

/>>>
socket.inet_ntoa(struct.pack('I',socket.htonl(3703717152)))         
'220.194.61.32'

unpack/pack和cpu,os無關;

socket.ntohl/htonl的輸出結果int型

對32 os,處理成signed 類型,首位1被處理成負數;
對 64位 os,則是unsigned類型;ip


(5)MySQL裏面的函數是inet_aton,
inet_ntoa 和Python的socket不一樣,直接實現ip string到network byte的轉換python裏面只能實現ip地址到network byte的2進制轉換:
mysql> select inet_aton('1.2.3.4'); -> 16909060 mysql> select inet_ntoa(16909060); -> 1.2.3.4

相關文章
相關標籤/搜索