နားလည်ထားရမယ့် အချက်
IPv4 address ဆိုတာ 32-bit ကိန်းတစ်ခုသာ ဖြစ်ပါတယ် — ဒီထက် ဘာမှ မပိုပါဘူး။ 3232238117 ဆိုတာ တရားဝင် IPv4 address တစ်ခုဖြစ်ပြီး၊ သူဟာ 192.168.10.37 နဲ့ တစ်ထပ်တည်း တူတဲ့ address ပါ။ Dotted-quad ရေးနည်းက လူအတွက် အဆင်ပြေအောင် လုပ်ထားတာသာ ဖြစ်ပါတယ် — 32 bit ကို 8-bit အပိုင်း လေးပိုင်း ခွဲ၊ တစ်ပိုင်းစီကို 0 ကနေ 255 အထိ ဒဿမကိန်းအဖြစ် ရေး၊ အစက်နဲ့ ဆက်လိုက်ရုံပါပဲ။ သင်မြင်ရတဲ့ octet တိုင်းက ကိန်းတစ်ခုတည်းရဲ့ bit ရှစ်လုံးသာ ဖြစ်ပါတယ် — ဒါကြောင့် 192.168.10.256 ဆိုတာ အဓိပ္ပာယ်မရှိတာဖြစ်ပြီး၊ address တွေကို string အဖြစ် နှိုင်းယှဉ်ရင် အဆင်မပြေဘဲ integer အဖြစ် နှိုင်းယှဉ်မှ မှန်ကန်တာ ဖြစ်ပါတယ်။
အရေးကြီးတဲ့ ဖွဲ့စည်းပုံကတော့ ဒီ 32 bit ကို နှစ်ပိုင်း ခွဲထားတာပါ။ ရှေ့ဆုံးက bit အစုအဝေးတစ်ခုက network ကို ဖော်ပြပြီး၊ ကျန်တဲ့ bit တွေက အဲဒီ network အတွင်းက host တစ်ခုကို ဖော်ပြပါတယ်။ အလွန်အရေးကြီးတာက address တစ်ခုတည်းကနေ ဒီအခွဲက ဘယ်နေရာမှာ ကျလဲ ဆိုတာ မသိနိုင်ပါဘူး — subnet mask လိုအပ်ပါတယ်။ Subnet mask ဆိုတာ နောက်ထပ် 32-bit တန်ဖိုးတစ်ခုဖြစ်ပြီး၊ network အပိုင်းအတွက် bit အားလုံး 1၊ host အပိုင်းအတွက် bit အားလုံး 0 ဖြစ်ပါတယ်။ address ကို mask နဲ့ AND လုပ်ရင် network address ရပြီး၊ ပြောင်းပြန်လှန်ထားတဲ့ mask နဲ့ AND လုပ်ရင် host number ရပါတယ်။
Mask ဟာ 1 တွေ တစ်တန်းတည်း ပြီးမှ 0 တွေ တစ်တန်းတည်း ဖြစ်နေတာမို့ bit 32 လုံးလုံး ရေးပြတာ ပိုနေပါတယ် — 1 ဘယ်နှစ်လုံး ဆိုတဲ့ အရေအတွက်ပဲ လိုအပ်ပါတယ်။ ဒါက CIDR notation ဖြစ်ပါတယ် — /24 ဆိုတာ 1 နှစ်ဆယ့်လေးလုံး၊ ဒါက 255.255.255.0 ပါ။ ဒါက လက်တွေ့မှာ အမြဲတမ်း အရေးပါပါတယ်၊ ဘာလို့လဲဆိုတော့ host တစ်ခုက packet တစ်ခုကို ဘာလုပ်ရမလဲ ဆုံးဖြတ်ဖို့ ဒီ စမ်းသပ်မှုကိုပဲ အတိအကျ သုံးလို့ပါ — destination ရဲ့ network part က သူ့ဟာနဲ့ တူရင် LAN ပေါ်မှာ တိုက်ရိုက် ပို့လိုက်တယ်၊ မတူရင် default gateway ဆီ လွှဲပေးလိုက်တယ်။ Mask ကို ပြောင်းလိုက်ရင် ဒီဆုံးဖြတ်ချက် ပြောင်းသွားပါတယ်။
192.168.10.37/24 AS 32 BITS
---------------------------
192 168 10 37 <- dotted quad (for humans)
11000000 10101000 00001010 00100101 <- the real 32-bit integer
[---- network: 24 bits ------] [ host ]
11111111 11111111 11111111 00000000 <- /24 mask = 255.255.255.0
all 1s: keep this part all 0s: this part varies per host
address AND mask -> 11000000 10101000 00001010 00000000
= 192.168.10.0 (the network address)
address AND ~mask -> 00000000 00000000 00000000 00100101
= 37 (host number in that net)
Same 32 bits, different mask, different meaning:
192.168.10.37/24 -> network 192.168.10.0 (8 host bits)
192.168.10.37/16 -> network 192.168.0.0 (16 host bits)
192.168.10.37/28 -> network 192.168.10.32 (4 host bits)လက်တွေ့ scenario နဲ့ ချိတ်ကြည့်မယ်
လက်တွေ့ ကြုံရမယ့် ချို့ယွင်းချက် တစ်ခု — တစ်ယောက်ယောက်က စက်တစ်လုံးရဲ့ address ကို 192.168.10.37 နဲ့ mask 255.255.0.0 လို့ သတ်မှတ်လိုက်တယ်၊ တခြား LAN တစ်ခုလုံးကတော့ 255.255.255.0 သုံးနေတယ်။ 192.168.10.x ထဲက အိမ်နီးချင်းတွေကို ping လုပ်တာ အလုပ်လုပ်နေသေးလို့ အားလုံး အဆင်ပြေသလို မြင်ရပါတယ် — ဒါပေမယ့် တခြားသူတွေအတွက် တခြား network ဖြစ်တဲ့ 192.168.11.5 ကို ဒီစက်တစ်လုံးကတော့ local လို့ မြင်နေပါပြီ။ အဲဒီ traffic ကို gateway ဆီ ပို့မယ့်အစား၊ ဝါယာကြိုးပေါ်မှာ မရှိတဲ့ host တစ်ခုအတွက် ARP လုပ်ပြီး connection က တိတ်တဆိတ် ရပ်တန့်သွားပါတယ်။ လက္ခဏာက "host အချို့ အလုပ်လုပ်ပြီး အချို့ timeout ဖြစ်တယ်" ဆိုတာဖြစ်ပြီး၊ အကြောင်းရင်းက mask တစ်ခု မှားနေတာပါ။
အသုံးချရမယ့် ကျိုးကြောင်းဆင်ခြင်မှုက အမြဲတမ်း အဆင့်သုံးဆင့်ပါပဲ။ ကိုယ့် address နဲ့ ကိုယ့် mask ကို ယူပြီး AND လုပ်ကာ ကိုယ့် network address ရယူပါ။ ပြီးရင် destination address ကို ယူပြီး ကိုယ့် mask ကို သုံးကာ သူ့ network address ရယူပါ။ နှစ်ခု တူရင် destination က ကိုယ့် link ပေါ်မှာ ရှိလို့ တိုက်ရိုက် ပို့လိုက်ပါ၊ မတူရင် default gateway ဆီ ပို့လိုက်ပါ။ ဒီနှိုင်းယှဉ်မှုက အထွက် packet တိုင်းအတွက် ဖြစ်ပေါ်နေပါတယ်။
အောက်က code က 192.168.10.37/24 အတွက် ဒီတွက်ချက်မှုကိုပဲ အတိအကျ run ပြပါတယ် — address ကို integer အဖြစ်၊ ပြီးရင် 32 bit အဖြစ်၊ ပြီးရင် mask၊ နောက်ဆုံးမှာ network part နဲ့ host part ကို ခွဲထုတ်ပေးတဲ့ AND ရလဒ် နှစ်ခုကို ရိုက်ထုတ်ပေးပါတယ်။
အတူတူ စမ်းရေးကြည့်မယ်
import ipaddress
iface = ipaddress.IPv4Interface("192.168.10.37/24")
addr = iface.ip
net = iface.network
print("address :", addr)
print("as one integer:", int(addr))
print("as 32 bits :", format(int(addr), "032b"))
print()
print("prefix length :", net.prefixlen, "network bits /",
32 - net.prefixlen, "host bits")
print("netmask :", net.netmask)
print("mask in bits :", format(int(net.netmask), "032b"))
print("hostmask :", net.hostmask)
print()
print("network addr :", net.network_address)
print("network part :", format(int(addr) & int(net.netmask), "032b"))
print("host part :", format(int(addr) & int(net.hostmask), "032b"))
print("host number :", int(addr) & int(net.hostmask))
print()
# Two addresses are "local" to each other only if the network parts match.
for other in ("192.168.10.200", "192.168.11.200"):
same = ipaddress.IPv4Address(other) in net
print("%-15s same network as %s ? %s" % (other, addr, same))
address : 192.168.10.37
as one integer: 3232238117
as 32 bits : 11000000101010000000101000100101
prefix length : 24 network bits / 8 host bits
netmask : 255.255.255.0
mask in bits : 11111111111111111111111100000000
hostmask : 0.0.0.255
network addr : 192.168.10.0
network part : 11000000101010000000101000000000
host part : 00000000000000000000000000100101
host number : 37
192.168.10.200 same network as 192.168.10.37 ? True
192.168.11.200 same network as 192.168.10.37 ? False၅ မိနစ် စမ်းကြည့်
IPv4Interface ကို "192.168.10.37/16" နဲ့ "192.168.10.37/28" အဖြစ် ပြောင်းပြီး run ကြည့်ပါ။ address bits တွေက အတူတူပဲ ဖြစ်နေပေမယ့် network address, host number, နှင့် 192.168.11.200 က same network ဟုတ်မဟုတ် ဆိုတဲ့ အဖြေတွေ ဘာကြောင့် ပြောင်းသွားလဲ ရှင်းပြပါ။
သတိလေးတစ်ချက်
IP address တွေကို string အဖြစ် နှိုင်းယှဉ်ခြင်း သို့မဟုတ် စီခြင်း — "192.168.10.9" က "192.168.10.10" ထက် ကြီးတယ်လို့ string နှိုင်းယှဉ်မှုက ပြောပါလိမ့်မယ်၊ ipaddress object ဒါမှမဟုတ် int အဖြစ် ပြောင်းပြီးမှ နှိုင်းယှဉ်ပါ
Address ကိုကြည့်ရုံနဲ့ network ဘယ်ဟာလဲ ခန့်မှန်းခြင်း — 10.1.2.3 ဆိုတာ /8 လား /24 လား /30 လား address ကနေ ဘယ်တော့မှ မသိနိုင်ဘဲ mask ကို အမြဲ စစ်ရပါမယ်
RFC 4632 — Classless Inter-domain Routing (CIDR) — Computer Networking