IPアドレスを二進⇔十進変換(ビット演算)

Python3で行います.

def binary_ip(ip):
    octets = [int(o) for o in ip.split('.')]
    ip = octets[0] << 24 | octets[1] << 16 | octets[2] << 8 | octets[3]
    return ip

def decimal_ip(bin_ip):
    return (bin_ip >> 24, bin_ip >> 16 & 0xff, bin_ip >> 8 & 0xff, bin_ip & 0xff)

binary_ip(’192.168.0.5′)を呼び出すとそれの数値表現 3232235525 が返ります.
decimal_ip(3232235525 )とするとタプル (192,168,0,5) が返ります.
ビット演算(AND, OR),ビットシフトしか使用しておらず,型変換も最小限に抑えているのでオーバーヘッドはないと思います.

つぎに,例を挙げます.
ホストマシンが192.168.10.5,サブネットマスクが255.255.255.0のネットワークのネットワークアドレスは何でしょうか.
ネットワークアドレスを求めるにはIPアドレスとサブネットマスクのANDを取るだけです.
これがソースとなります.

ip = '192.168.10.5'
mask = '255.255.255.0'
net = binary_ip(ip) & binary_ip(mask)
net_h = decimal_ip(net)
print('subnet ip: {0[0]}.{0[1]}.{0[2]}.{0[3]}'.format(net_h))

192.168.10.5は

1100 0000  1010 1000  0000 1010  0000 0101

とあらわされます.

一方,255.255.255.0は

1111 1111  1111 1111  1111 1111  0000 0000

です.
これのANDを取ると,

1100 0000  1010 1000  0000 1010  0000 0000

となります.10進では 3232238080 です.

3232238080が結果ですが,見慣れたIPアドレスではありません.人間に読みやすいようにオクテットごとに分解する書き方で出力させましょう.

3232238080をdecimal_ipにて右シフトを行います.
上位8ビット(第一オクテット)から見ていきます.
24ビットの右シフトを行うと,

0000 0000  0000 0000  0000 0000  1100 0000

となります.これは192です.
第二オクテットを算出するために,16ビットの右シフトをします.

0000 0000  0000 0000  1100 0000  1010 1000

49320となってしまいます.これは,第一オクテットが入っているためです.
第二オクテットだけを取り出すには,ビットシフト後の結果から下位8ビットだけを取り出します.それには,0xFF

0000 0000  0000 0000  0000 0000  1111 1111

とのANDを取ればいいです.結果として

0000 0000  0000 0000  0000 0000  1010 1000

168が出てきます.
これを第三,第四オクテットにも適用しますが,略します.

出力はこうなります:

subnet ip: 192.168.10.0

コメントを残す

メールアドレスが公開されることはありません。

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>