เครือข่าย TCP/IP และ UDP
UAT 105 เทคโนโลยีดิจิทัลและเครือข่าย
บทเรียน
เมื่อเรียนจบโมดูลนี้ ผู้เรียนจะสามารถ
- อธิบายชั้นโปรโตคอลและการห่อหุ้มข้อมูลจาก MAVLink ลงไปถึงคลื่นวิทยุ
- วางแผนที่อยู่ IPv4 และแบ่ง subnet ด้วยโมดูล ipaddress และแยกประเภทที่อยู่พิเศษได้
- เปรียบเทียบ TCP กับ UDP และอธิบายว่าทำไม telemetry นิยมใช้ UDP
- ตั้งค่าและทดสอบเครือข่ายสถานีภาคพื้น และคำนวณภาระข้อมูลกับการลดทอนสัญญาณในที่โล่ง
ทำไมต้องรู้
ภาคสนามวันหนึ่ง โน้ตบุ๊กสถานีภาคพื้นเชื่อม Wi-Fi ได้ แต่ QGroundControl ไม่เห็นโดรน ปัญหาอาจอยู่ที่ที่อยู่ IP คนละวง พอร์ตผิด ไฟร์วอลล์บล็อก หรือสัญญาณอ่อนเกินไป ผู้ที่เข้าใจเครือข่ายเป็นชั้นจะไล่หาสาเหตุได้ทีละชั้น แทนที่จะลองสุ่มแก้ไปเรื่อย ๆ
ชั้นโปรโตคอลและการห่อหุ้มข้อมูล
โปรโตคอล (protocol) คือข้อตกลงว่าจะส่งข้อมูลรูปแบบใดและตอบสนองอย่างไร เครือข่ายอินเทอร์เน็ตแบ่งงานเป็นชั้น แต่ละชั้นทำหน้าที่เดียวและใช้บริการของชั้นล่าง ตำราของ Kurose และ Ross แบ่งเป็นห้าชั้น
เมื่อสถานีภาคพื้นส่งข้อความ MAVLink ข้อความจะถูก ห่อหุ้ม (encapsulate) ลงไปทีละชั้น เหมือนใส่จดหมายในซอง แล้วใส่ซองในกล่องพัสดุ
- ชั้น แอปพลิเคชัน สร้างเฟรม MAVLink
- ชั้น ทรานสปอร์ต เติมส่วนหัว UDP 8 ไบต์ ระบุ พอร์ต (port) ต้นทางและปลายทาง เพื่อบอกว่าส่งให้โปรแกรมใด
- ชั้น เครือข่าย เติมส่วนหัว IPv4 อย่างน้อย 20 ไบต์ ระบุ ที่อยู่ IP ต้นทางและปลายทาง เพื่อบอกว่าส่งให้เครื่องใด
- ชั้น ลิงก์ และ กายภาพ เช่น Wi-Fi แปลงเป็นเฟรมไร้สายและคลื่นวิทยุ
ฝั่งรับแกะซองย้อนกลับทีละชั้น ส่วนหัวเหล่านี้ทำให้ข้อมูลที่ส่งจริงมากกว่าข้อมูลของเรา
ตัวอย่างที่ 1 ภาระข้อมูลเมื่อนับส่วนหัว
ส่งข้อความ MAVLink ขนาด 50 ไบต์ 10 ครั้งต่อวินาที ผ่าน UDP บน IPv4 (ไม่มี option และไม่รวมข้อความหลายชิ้นในแพ็กเก็ตเดียว) ตัวอย่างนี้มาจากหน่วยความรู้การสื่อสารและ MAVLink ของคลังความรู้โดรน
mavlink_bytes, rate_hz = 50, 10
udp_ip_header = 8 + 20
print(8 * mavlink_bytes * rate_hz, "bit/s at the MAVLink layer")
print(8 * (mavlink_bytes + udp_ip_header) * rate_hz, "bit/s including UDP and IPv4 headers")
print(f"header overhead {udp_ip_header / (mavlink_bytes + udp_ip_header):.0%}")
4000 bit/s at the MAVLink layer
6240 bit/s including UDP and IPv4 headers
header overhead 36%
ส่วนหัวกินไปถึง 36% ของข้อมูลที่ส่ง และยังไม่ได้นับส่วนหัวของ Wi-Fi ดังนั้นเมื่อเทียบกับความจุลิงก์ ต้องนับทุกชั้นในระดับเดียวกัน
ที่อยู่ IPv4 และ subnet
ที่อยู่ IPv4 ยาว 32 บิต เขียนเป็นเลขฐานสิบสี่ชุดคั่นด้วยจุด เช่น 192.168.10.20 ที่อยู่แบ่งเป็นสองส่วน คือส่วน เครือข่าย กับส่วน เครื่อง (host) การเขียนแบบ CIDR เช่น /24 บอกว่า 24 บิตแรกเป็นส่วนเครือข่าย เครื่องที่ส่วนเครือข่ายเหมือนกันอยู่ใน subnet เดียวกันและคุยกันได้โดยตรง
ใน subnet หนึ่งมีที่อยู่ ตัว แต่ที่อยู่แรกใช้เป็นชื่อเครือข่าย และที่อยู่สุดท้ายใช้กระจายข้อความถึงทุกเครื่อง (broadcast) จึงเหลือให้เครื่องใช้ ตัว
import ipaddress
net = ipaddress.ip_network("192.168.10.0/24")
print(net.num_addresses, net.num_addresses - 2, net.netmask, net.broadcast_address)
for sub in net.subnets(new_prefix=26):
hosts = list(sub.hosts())
print(sub, hosts[0], "-", hosts[-1], len(hosts), "hosts")
256 254 255.255.255.0 192.168.10.255
192.168.10.0/26 192.168.10.1 - 192.168.10.62 62 hosts
192.168.10.64/26 192.168.10.65 - 192.168.10.126 62 hosts
192.168.10.128/26 192.168.10.129 - 192.168.10.190 62 hosts
192.168.10.192/26 192.168.10.193 - 192.168.10.254 62 hosts
การแบ่ง /24 เป็น /26 สี่วง ช่วยแยกอุปกรณ์เป็นกลุ่ม เช่น วงแรกสำหรับสถานีภาคพื้น วงที่สองสำหรับโดรน โดยแต่ละวงยังมีที่อยู่ให้ใช้ 62 เครื่อง
ที่อยู่พิเศษที่ต้องรู้จัก
- ที่อยู่ส่วนตัว ตาม RFC 1918 ได้แก่
10.0.0.0/8,172.16.0.0/12และ192.168.0.0/16ใช้ในเครือข่ายภายใน ไม่ถูกส่งต่อบนอินเทอร์เน็ต - loopback
127.0.0.0/8วนกลับเข้าเครื่องตัวเอง SITL บนเครื่องเดียวกับสถานีภาคพื้นจึงคุยกันผ่าน127.0.0.1 - link-local
169.254.0.0/16เครื่องตั้งให้ตัวเองเมื่อหาเซิร์ฟเวอร์ DHCP ไม่พบ ถ้าเห็นที่อยู่นี้แปลว่าเครื่องยังไม่ได้ที่อยู่จากเราเตอร์
RFC1918 = [ipaddress.ip_network(n) for n in ("10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16")]
for a in ["10.1.2.3", "172.20.0.5", "192.168.10.20", "8.8.8.8", "127.0.0.1", "169.254.7.9"]:
ip = ipaddress.ip_address(a)
rfc1918 = any(ip in n for n in RFC1918)
print(f"{a:<14} rfc1918={rfc1918!s:<5} is_private={ip.is_private!s:<5} loopback={ip.is_loopback!s:<5} link_local={ip.is_link_local}")
10.1.2.3 rfc1918=True is_private=True loopback=False link_local=False
172.20.0.5 rfc1918=True is_private=True loopback=False link_local=False
192.168.10.20 rfc1918=True is_private=True loopback=False link_local=False
8.8.8.8 rfc1918=False is_private=False loopback=False link_local=False
127.0.0.1 rfc1918=False is_private=True loopback=True link_local=False
169.254.7.9 rfc1918=False is_private=True loopback=False link_local=True
สังเกตว่า is_private ของ Python ให้ True กับ loopback และ link-local ด้วย เพราะนิยามของ Python คือ “ไม่ใช่ที่อยู่สาธารณะบนอินเทอร์เน็ตตามทะเบียนของ IANA” ซึ่งกว้างกว่า RFC 1918 ถ้าต้องการตรวจเฉพาะช่วงส่วนตัวของ RFC 1918 ต้องเขียนตรวจเอง
IPv6 ใช้ที่อยู่ยาว 128 บิต แก้ปัญหาที่อยู่ IPv4 ไม่พอ ส่วนหัวมีขนาดคงที่ 40 ไบต์ เครือข่ายมือถือและระบบคลาวด์ใช้ IPv6 มากขึ้นเรื่อย ๆ แต่เครือข่ายภาคสนามขนาดเล็กยังนิยม IPv4 ส่วนตัว
TCP กับ UDP
ชั้นทรานสปอร์ตมีโปรโตคอลหลักสองตัว
- TCP เริ่มด้วยการ จับมือสามขั้น (three-way handshake) รับประกันว่าข้อมูลครบและเรียงลำดับ ถ้าแพ็กเก็ตหายจะส่งซ้ำ เหมาะกับงานที่ข้อมูลต้องครบทุกไบต์ เช่น ดาวน์โหลดไฟล์ log หรือเว็บ
- UDP ส่งทีละ datagram โดยไม่จับมือ ไม่ยืนยัน และไม่ส่งซ้ำ มีส่วนหัวเพียง 8 ไบต์ เหมาะกับข้อมูลที่ต้องสดใหม่
MAVLink บนเครือข่าย IP นิยมใช้ UDP สถานีภาคพื้นเช่น QGroundControl รอรับที่ พอร์ต UDP 14550 เหตุผลคือ telemetry เป็นข้อมูลที่ข้อมูลใหม่มาแทนข้อมูลเก่าเสมอ ถ้าตำแหน่งเมื่อ 0.5 วินาทีก่อนหายไป การรอส่งซ้ำด้วย TCP จะยิ่งทำให้ข้อมูลใหม่ที่ตามมาต้องรอคิว ข้อมูลทั้งสายจึงล่าช้า การยอมเสียบางแพ็กเก็ตแต่ได้ข้อมูลล่าสุดเร็วกว่าจึงคุ้มกว่า
import socket
rx = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
rx.bind(("127.0.0.1", 0))
rx.settimeout(2)
port = rx.getsockname()[1]
tx = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
heartbeat = bytes.fromhex("fd 09 00 00 00 01 01 00 00 00 04 00 00 00 02 03 51 03 03 7e 22")
tx.sendto(heartbeat, ("127.0.0.1", port))
data, sender = rx.recvfrom(2048)
print(len(data), "bytes, first byte", hex(data[0]), "same as sent:", data == heartbeat, "from", sender[0])
tx.close()
rx.close()
21 bytes, first byte 0xfd same as sent: True from 127.0.0.1
โปรแกรมนี้ส่งเฟรม HEARTBEAT จากโมดูล 1 ผ่าน UDP บน loopback ในงานจริงให้ผูกพอร์ตรับเป็น 14550 แทน 0 (เลข 0 ให้ระบบเลือกพอร์ตว่างเอง ใช้เพื่อไม่ให้ชนกับโปรแกรมอื่นตอนทดสอบ) และควรตั้ง settimeout เสมอ ไม่เช่นนั้นโปรแกรมจะรอค้างตลอดไปถ้าไม่มีข้อมูลเข้ามา
ลิงก์ไร้สายและการลดทอนสัญญาณ
- Wi-Fi ตามมาตรฐาน IEEE 802.11 ใช้ย่าน 2.4, 5 และ 6 GHz รุ่นล่าสุด Wi-Fi 7 (IEEE 802.11be) ได้รับอนุมัติเดือนกันยายน 2024 และตีพิมพ์เดือนกรกฎาคม 2025 ระยะของ Wi-Fi ทั่วไปสั้น เหมาะกับงานในระยะสายตา
- เครือข่ายมือถือ 4G/5G มาตรฐาน 5G ชุดแรกคือ 3GPP Release 15 และ 3GPP มีข้อกำหนด TS 22.125 สำหรับรองรับอากาศยานไร้คนขับ เช่น การระบุตัวตนของโดรนและลิงก์ควบคุมผ่านเครือข่ายเซลลูลาร์
- วิทยุ telemetry เช่น SiK ใช้พอร์ตอนุกรม ไม่ได้ใช้ IP ส่งได้ไกลกว่า Wi-Fi แต่ช้ากว่ามาก
กำลังสัญญาณลดลงตามระยะแม้ไม่มีสิ่งกีดขวาง ITU-R P.525-5 ให้สูตร การลดทอนในที่โล่ง (free-space loss) ที่คลื่นแผ่กระจายออกเป็นทรงกลม ระยะเพิ่มสองเท่า การลดทอนเพิ่ม dB
ตัวอย่างที่ 2 งบกำลังของลิงก์ 2.4 GHz
ใช้ค่าจากโจทย์สังเคราะห์ของคลังความรู้โดรน กำลังส่ง 20 dBm สายอากาศ 2 dBi ทั้งสองฝั่ง การสูญเสียอื่น 2 dB และความไวของตัวรับ −90 dBm
import math
def fspl_db(d_m, f_hz):
return 20 * math.log10(4 * math.pi * d_m * f_hz / 299_792_458)
for d in (500, 1000, 2000):
loss = fspl_db(d, 2.4e9)
received = 20 + 2 + 2 - loss - 2
print(f"{d:>5} m loss {loss:6.2f} dB received {received:7.2f} dBm margin {received + 90:5.2f} dB")
print(f"1000 m at 5.8 GHz {fspl_db(1000, 5.8e9):.2f} dB, at 433 MHz {fspl_db(1000, 433e6):.2f} dB")
500 m loss 94.03 dB received -72.03 dBm margin 17.97 dB
1000 m loss 100.05 dB received -78.05 dBm margin 11.95 dB
2000 m loss 106.07 dB received -84.07 dBm margin 5.93 dB
1000 m at 5.8 GHz 107.72 dB, at 433 MHz 85.18 dB
ส่วนเผื่อ (margin) ลดลงประมาณ 6 dB ทุกครั้งที่ระยะเพิ่มสองเท่า และความถี่สูงลดทอนมากกว่าความถี่ต่ำที่ระยะเท่ากัน ตัวเลขนี้เป็นแบบจำลองในที่โล่งเท่านั้น ไม่รวมสิ่งกีดขวาง การสะท้อน และสัญญาณรบกวน ส่วนเผื่อเป็นบวกจึงไม่ได้รับประกันว่าลิงก์จริงจะใช้ได้
กฎการใช้คลื่นความถี่
ความถี่และกำลังส่งที่ใช้ได้ในไทยอยู่ภายใต้ประกาศของ กสทช. และกฎสำหรับวิทยุของโดรนกำลังอยู่ระหว่างปรับปรุง ก่อนใช้วิทยุจริงต้องตรวจประกาศฉบับล่าสุด ตัวเลขกำลังส่งในตัวอย่างเป็นโจทย์สำหรับฝึกคำนวณ ไม่ใช่ค่าที่อนุญาต
ตั้งค่าเครือข่ายสถานีภาคพื้น
ขั้นตอนไล่ปัญหาเมื่อสถานีภาคพื้นไม่เห็นโดรน ให้ไล่จากชั้นล่างขึ้นบน
- ลิงก์ เชื่อม Wi-Fi ถูกเครือข่ายหรือไม่ สัญญาณแรงพอหรือไม่
- เครือข่าย ดูที่อยู่ของเครื่องด้วย
ipconfig(Windows) หรือip addr(Linux) ว่าอยู่ใน subnet เดียวกันหรือไม่ ถ้าได้169.254.x.xแปลว่ายังไม่ได้ที่อยู่ ทดสอบถึงกันด้วยping 192.168.10.30 - ทรานสปอร์ต โดรนส่งไปพอร์ตที่สถานีภาคพื้นรอรับหรือไม่ และไฟร์วอลล์ของ Windows อนุญาต UDP 14550 หรือไม่
- แอปพลิเคชัน ดูข้อมูลที่ไหลจริงด้วย Wireshark ตัวกรอง
udp.port == 14550
ปฏิบัติการประจำโมดูล
ปฏิบัติการ: จับ telemetry ของ SITL ด้วย Wireshark
- เปิด SITL และ QGroundControl บนเครื่องเดียวกัน แล้วเปิด Wireshark จับข้อมูลที่อินเทอร์เฟซ loopback (บน Windows ต้องติดตั้ง Npcap ที่มากับ Wireshark ก่อน)
- ใช้ตัวกรอง
udp.port == 14550นับจำนวนแพ็กเก็ตต่อวินาที เปิดดูไบต์ของแพ็กเก็ตหนึ่ง แล้วหา0xFDต้นเฟรม MAVLink ใต้ส่วนหัว UDP และ IP - หยุดการส่งต่อข้อมูลของ SITL ชั่วคราว (ตามหน่วยความรู้ “C2 และเหตุผิดปกติใน simulation”) แล้วบันทึกว่า QGroundControl แสดงอะไร และ log บอกว่าโหมดการบินเปลี่ยนหรือไม่
- จัดเครือข่ายตามภาพที่ 3 ด้วยเราเตอร์จริง ตั้ง IP แบบคงที่ให้คอมพิวเตอร์บนโดรน และทดสอบ
pingทุกคู่ แล้วบันทึกผังเครือข่ายพร้อมที่อยู่และพอร์ตลงใบงาน
ข้อผิดพลาดที่พบบ่อย
ระวัง
- เครื่องอยู่คนละ subnet เช่น
192.168.1.20/24กับ192.168.10.30/24จะส่งถึงกันโดยตรงไม่ได้ - ไม่ตั้ง timeout ของ socket โปรแกรมค้างเงียบเมื่อไม่มีข้อมูลเข้า
- ใช้ TCP กับ telemetry ในลิงก์ที่แพ็กเก็ตหายบ่อย การส่งซ้ำทำให้ข้อมูลทั้งสายล่าช้า
- ลืมไฟร์วอลล์ Windows มักบล็อกพอร์ตขาเข้าของโปรแกรมที่เพิ่งติดตั้ง
- ใช้ margin ในที่โล่งเป็นระยะใช้งานจริง สิ่งกีดขวางและสัญญาณรบกวนลดระยะลงได้มาก
สรุป
- เครือข่ายแบ่งเป็นชั้น ข้อมูลถูกห่อด้วยส่วนหัวของ UDP/TCP และ IP ก่อนออกทางลิงก์ ส่วนหัวเพิ่มภาระข้อมูลอย่างมีนัยสำคัญ
- ที่อยู่ IPv4 ยาว 32 บิต แบ่งเป็นส่วนเครือข่ายและส่วนเครื่องตาม prefix ต้องรู้จักที่อยู่ส่วนตัว loopback และ link-local
- TCP รับประกันความครบถ้วนแต่อาจล่าช้า UDP เร็วแต่ไม่รับประกัน telemetry ของ MAVLink จึงนิยมใช้ UDP พอร์ต 14550
- การลดทอนในที่โล่งเพิ่มประมาณ 6 dB ต่อระยะสองเท่า ไล่ปัญหาเครือข่ายจากชั้นล่างขึ้นบน
แบบฝึกตรวจความเข้าใจ
- subnet
/27มีที่อยู่ให้เครื่องใช้ได้กี่ตัว 172.31.5.9อยู่ในช่วงส่วนตัวของ RFC 1918 หรือไม่- ส่งข้อความ MAVLink 40 ไบต์ 20 ครั้งต่อวินาทีผ่าน UDP/IPv4 ใช้กี่ bit/s เมื่อรวมส่วนหัว
- ระยะเพิ่มจาก 1 km เป็น 4 km การลดทอนในที่โล่งเพิ่มขึ้นประมาณกี่ dB
- โน้ตบุ๊กได้ที่อยู่
169.254.12.3บอกอะไร
เฉลย
- เครื่อง
- อยู่ เพราะ
172.16.0.0/12ครอบคลุม 172.16.0.0 ถึง 172.31.255.255 - bit/s
- ระยะเพิ่ม 4 เท่า เท่ากับเพิ่มสองเท่าสองครั้ง จึงเพิ่ม dB
- เครื่องหาเซิร์ฟเวอร์ DHCP ไม่พบจึงตั้งที่อยู่ link-local ให้ตัวเอง ต้องตรวจการเชื่อมต่อหรือตั้ง IP เอง
สรุปสูตรสำคัญ
| จำนวนที่อยู่ใน subnet ความยาว prefix p | |
| อัตราบิตรวมส่วนหัว | |
| การลดทอนในที่โล่ง (ITU-R P.525) | |
| กำลังรับและส่วนเผื่อ |
แหล่งอ้างอิงหลัก
- Kurose, J. F., & Ross, K. W. (2025). Computer networking: A top-down approach (9th ed.). Pearson. link
- Postel, J. (1981). Internet Protocol (RFC 791). RFC Editor. link
- Postel, J. (1980). User Datagram Protocol (RFC 768). RFC Editor. link
- Eddy, W. (Ed.). (2022). Transmission Control Protocol (TCP) (RFC 9293). RFC Editor. link
- Deering, S., & Hinden, R. (2017). Internet Protocol, version 6 (IPv6) specification (RFC 8200). RFC Editor. link
- Rekhter, Y., Moskowitz, B., Karrenberg, D., de Groot, G. J., & Lear, E. (1996). Address allocation for private internets (RFC 1918). RFC Editor. link
- Fuller, V., & Li, T. (2006). Classless inter-domain routing (CIDR): The Internet address assignment and aggregation plan (RFC 4632). RFC Editor. link
- Internet Assigned Numbers Authority. IANA IPv4 special-purpose address registry. link
- IEEE. (2025). IEEE Std 802.11be-2024: Amendment 2, enhancements for extremely high throughput (EHT). link
- 3GPP. Unmanned Aerial System (UAS) support in 3GPP (TS 22.125). link
- International Telecommunication Union. (2024). Calculation of free-space attenuation (Recommendation ITU-R P.525-5). link
- Wireshark Foundation. Wireshark user's guide. link
- Python Software Foundation. ipaddress, socket, hashlib and hmac modules. The Python standard library (3.14). link
อ่านเพิ่มเติม
ศึกษาหน่วยความรู้ที่กำหนดล่วงหน้า ดูสื่อประกอบ และทำ quiz ประจำโมดูล
เครือข่าย TCP/IP สำหรับงานภาคสนาม
Wireshark
การสื่อสารโดรนและ MAVLink
C2 และเหตุผิดปกติใน simulation
ในชั้นเรียน / ภาคสนาม
ปฏิบัติการในห้องแล็บหรือภาคสนามตามใบงาน พร้อม checklist ความปลอดภัย
หลักฐานการเรียนรู้: ใบงานที่ผ่านการตรวจและผล quiz