โปรโตคอลเครือข่ายและการวิเคราะห์ (Network Protocols and Analysis)

1. บทนำสู่โปรโตคอลเครือข่าย

1.1 ความหมายของโปรโตคอลเครือข่าย (Network Protocol)

โปรโตคอลเครือข่าย (Network Protocol) คือชุดของกฎเกณฑ์และมาตรฐานที่กำหนดวิธีการสื่อสารระหว่างอุปกรณ์ในเครือข่ายคอมพิวเตอร์ โปรโตคอลกำหนดรูปแบบข้อมูล (Data Format), ลำดับการส่งข้อมูล (Sequence), และวิธีการตอบสนองต่อข้อผิดพลาด (Error Handling)

1.2 แบบจำลอง OSI และ TCP/IP

การทำความเข้าใจโปรโตคอลเครือข่ายจำเป็นต้องเข้าใจ แบบจำลองชั้น (Layered Model) ที่ใช้ในการออกแบบและอธิบายการทำงานของเครือข่าย

graph TB
    subgraph OSI["แบบจำลอง OSI (OSI Model)"]
        direction TB
        L7["ชั้นที่ 7: Application
แอปพลิเคชัน"] L6["ชั้นที่ 6: Presentation
การนำเสนอ"] L5["ชั้นที่ 5: Session
เซสชัน"] L4["ชั้นที่ 4: Transport
ขนส่ง"] L3["ชั้นที่ 3: Network
เครือข่าย"] L2["ชั้นที่ 2: Data Link
เชื่อมต่อข้อมูล"] L1["ชั้นที่ 1: Physical
กายภาพ"] L7 --> L6 --> L5 --> L4 --> L3 --> L2 --> L1 end subgraph TCPIP["แบบจำลอง TCP/IP"] direction TB T4["Application Layer
ชั้นแอปพลิเคชัน"] T3["Transport Layer
ชั้นขนส่ง"] T2["Internet Layer
ชั้นอินเทอร์เน็ต"] T1["Network Access Layer
ชั้นเข้าถึงเครือข่าย"] T4 --> T3 --> T2 --> T1 end L7 -.-> T4 L6 -.-> T4 L5 -.-> T4 L4 -.-> T3 L3 -.-> T2 L2 -.-> T1 L1 -.-> T1 style L7 fill:#458588,stroke:#83a598,color:#ebdbb2 style L6 fill:#458588,stroke:#83a598,color:#ebdbb2 style L5 fill:#458588,stroke:#83a598,color:#ebdbb2 style L4 fill:#d79921,stroke:#fabd2f,color:#282828 style L3 fill:#98971a,stroke:#b8bb26,color:#282828 style L2 fill:#b16286,stroke:#d3869b,color:#ebdbb2 style L1 fill:#b16286,stroke:#d3869b,color:#ebdbb2 style T4 fill:#458588,stroke:#83a598,color:#ebdbb2 style T3 fill:#d79921,stroke:#fabd2f,color:#282828 style T2 fill:#98971a,stroke:#b8bb26,color:#282828 style T1 fill:#b16286,stroke:#d3869b,color:#ebdbb2

1.3 ประวัติความเป็นมาของโปรโตคอลเครือข่าย

flowchart LR
    subgraph Era1["ยุคบุกเบิก (1960s-1970s)"]
        A1["1969: ARPANET
เครือข่ายแรก"] A2["1974: TCP/IP
ถูกออกแบบ"] A3["1978: IPv4
เริ่มพัฒนา"] A1 --> A2 --> A3 end subgraph Era2["ยุคมาตรฐาน (1980s-1990s)"] B1["1981: IPv4
RFC 791"] B2["1983: ARPANET
ใช้ TCP/IP"] B3["1995: IPv6
เริ่มพัฒนา"] B1 --> B2 --> B3 end subgraph Era3["ยุคปัจจุบัน (2000s-ปัจจุบัน)"] C1["2004: IPv6
มาตรฐานสมบูรณ์"] C2["2011: IPv4
หมดช่วงที่อยู่"] C3["ปัจจุบัน: Dual Stack
IPv4/IPv6"] C1 --> C2 --> C3 end Era1 --> Era2 --> Era3 style A1 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style A2 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style A3 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style B1 fill:#d79921,stroke:#fabd2f,color:#282828 style B2 fill:#d79921,stroke:#fabd2f,color:#282828 style B3 fill:#d79921,stroke:#fabd2f,color:#282828 style C1 fill:#98971a,stroke:#b8bb26,color:#282828 style C2 fill:#98971a,stroke:#b8bb26,color:#282828 style C3 fill:#98971a,stroke:#b8bb26,color:#282828

2. โปรโตคอลชั้นขนส่ง (Transport Layer Protocols)

ชั้นขนส่ง (Transport Layer) เป็นชั้นที่รับผิดชอบการส่งข้อมูลระหว่างกระบวนการ (Process-to-Process Communication) บนโฮสต์ต้นทางและปลายทาง โดยโปรโตคอลหลักในชั้นนี้คือ TCP และ UDP

2.1 โปรโตคอล TCP (Transmission Control Protocol)

2.1.1 ความหมายและคุณสมบัติของ TCP

TCP (Transmission Control Protocol) คือโปรโตคอลที่ให้บริการการส่งข้อมูลแบบ เชื่อมต่อ (Connection-Oriented) และ เชื่อถือได้ (Reliable) โดยมีคุณสมบัติหลักดังนี้:

2.1.2 โครงสร้างส่วนหัว TCP (TCP Header Structure)

graph TB
    subgraph TCPHeader["โครงสร้างส่วนหัว TCP (TCP Header) - 20 ไบต์ขั้นต่ำ"]
        direction TB
        R1["Source Port (16 บิต) | Destination Port (16 บิต)"]
        R2["Sequence Number (32 บิต)"]
        R3["Acknowledgment Number (32 บิต)"]
        R4["Data Offset (4 บิต) | Reserved (3 บิต) | Flags (9 บิต) | Window Size (16 บิต)"]
        R5["Checksum (16 บิต) | Urgent Pointer (16 บิต)"]
        R6["Options (ถ้ามี) | Padding"]
        R1 --> R2 --> R3 --> R4 --> R5 --> R6
    end
    
    style R1 fill:#458588,stroke:#83a598,color:#ebdbb2
    style R2 fill:#98971a,stroke:#b8bb26,color:#282828
    style R3 fill:#98971a,stroke:#b8bb26,color:#282828
    style R4 fill:#d79921,stroke:#fabd2f,color:#282828
    style R5 fill:#d65d0e,stroke:#fe8019,color:#ebdbb2
    style R6 fill:#b16286,stroke:#d3869b,color:#ebdbb2
ฟิลด์ ขนาด คำอธิบาย
Source Port 16 บิต หมายเลขพอร์ตต้นทาง (0-65535)
Destination Port 16 บิต หมายเลขพอร์ตปลายทาง (0-65535)
Sequence Number 32 บิต หมายเลขลำดับของไบต์แรกในเซกเมนต์
Acknowledgment Number 32 บิต หมายเลขลำดับของไบต์ถัดไปที่คาดว่าจะได้รับ
Data Offset 4 บิต ความยาวของส่วนหัว (หน่วยเป็น 32-bit words)
Flags 9 บิต ธง URG, ACK, PSH, RST, SYN, FIN และอื่นๆ
Window Size 16 บิต ขนาดหน้าต่างรับ (Receive Window)
Checksum 16 บิต ค่าตรวจสอบความถูกต้อง
Urgent Pointer 16 บิต ชี้ไปยังข้อมูลเร่งด่วน (ถ้า URG=1)

2.1.3 กระบวนการ Three-Way Handshake

Three-Way Handshake คือกระบวนการสร้างการเชื่อมต่อ TCP ประกอบด้วย 3 ขั้นตอน:

sequenceDiagram
    participant C as ไคลเอนต์ (Client)
    participant S as เซิร์ฟเวอร์ (Server)
    
    Note over C,S: กระบวนการสร้างการเชื่อมต่อ (Connection Establishment)
    
    C->>S: SYN (seq=x)
    Note right of C: ขั้นที่ 1: ส่ง SYN
ขอสร้างการเชื่อมต่อ S->>C: SYN-ACK (seq=y, ack=x+1) Note left of S: ขั้นที่ 2: ตอบรับ SYN
และส่ง SYN กลับ C->>S: ACK (seq=x+1, ack=y+1) Note right of C: ขั้นที่ 3: ยืนยัน SYN
ของเซิร์ฟเวอร์ Note over C,S: การเชื่อมต่อสำเร็จ (ESTABLISHED) C->>S: ข้อมูล (Data) S->>C: ACK S->>C: ข้อมูล (Data) C->>S: ACK Note over C,S: กระบวนการยุติการเชื่อมต่อ (Connection Termination) C->>S: FIN (seq=m) S->>C: ACK (ack=m+1) S->>C: FIN (seq=n) C->>S: ACK (ack=n+1) Note over C,S: การเชื่อมต่อถูกปิด (CLOSED)

คำอธิบายกระบวนการ:

  1. SYN (Synchronize): ไคลเอนต์ส่งเซกเมนต์ SYN พร้อมหมายเลขลำดับเริ่มต้น (Initial Sequence Number - ISN) ไปยังเซิร์ฟเวอร์
  2. SYN-ACK: เซิร์ฟเวอร์ตอบกลับด้วย SYN-ACK โดยยืนยัน (ACK) หมายเลขลำดับของไคลเอนต์ และส่ง ISN ของตนเอง
  3. ACK (Acknowledge): ไคลเอนต์ส่ง ACK ยืนยันหมายเลขลำดับของเซิร์ฟเวอร์ การเชื่อมต่อพร้อมใช้งาน

2.1.4 การควบคุมการไหล (Flow Control)

TCP ใช้กลไก Sliding Window เพื่อควบคุมอัตราการส่งข้อมูล

graph LR
    subgraph Sender["ผู้ส่ง (Sender)"]
        S1["ส่งแล้ว
รอ ACK"] S2["ส่งได้
(Window)"] S3["ยังส่งไม่ได้"] end subgraph Receiver["ผู้รับ (Receiver)"] R1["รับแล้ว
ส่ง ACK"] R2["Buffer
ว่าง"] R3["รอข้อมูล"] end S1 --> |"ACK"| R1 S2 --> |"Data"| R2 style S1 fill:#98971a,stroke:#b8bb26,color:#282828 style S2 fill:#d79921,stroke:#fabd2f,color:#282828 style S3 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style R1 fill:#98971a,stroke:#b8bb26,color:#282828 style R2 fill:#d79921,stroke:#fabd2f,color:#282828 style R3 fill:#458588,stroke:#83a598,color:#ebdbb2

สูตรคำนวณ Throughput สูงสุดของ TCP:

Throughput = Window Size RTT

โดยที่:

2.1.5 การควบคุมความคับคั่ง (Congestion Control)

TCP ใช้อัลกอริทึมหลายตัวในการควบคุมความคับคั่ง:

อัลกอริทึม คำอธิบาย การทำงาน
Slow Start เริ่มต้นช้า เพิ่ม cwnd เป็นสองเท่าทุกๆ RTT จนถึง ssthresh
Congestion Avoidance หลีกเลี่ยงความคับคั่ง เพิ่ม cwnd ทีละ 1 MSS ต่อ RTT
Fast Retransmit ส่งซ้ำเร็ว ส่งซ้ำเมื่อได้รับ 3 Duplicate ACKs
Fast Recovery ฟื้นตัวเร็ว ลด cwnd ลงครึ่งหนึ่งแทนที่จะเริ่มใหม่
graph TD
    subgraph CongestionControl["อัลกอริทึมควบคุมความคับคั่ง"]
        A["เริ่มต้น
cwnd = 1 MSS"] B{"cwnd < ssthresh?"} C["Slow Start
cwnd = cwnd × 2"] D["Congestion Avoidance
cwnd = cwnd + 1"] E{"เกิด Timeout?"} F{"3 Duplicate
ACKs?"} G["ssthresh = cwnd/2
cwnd = 1 MSS"] H["Fast Recovery
ssthresh = cwnd/2
cwnd = ssthresh + 3"] A --> B B -->|ใช่| C B -->|ไม่| D C --> E D --> E E -->|ใช่| G E -->|ไม่| F F -->|ใช่| H F -->|ไม่| B G --> A H --> D end style A fill:#458588,stroke:#83a598,color:#ebdbb2 style B fill:#d79921,stroke:#fabd2f,color:#282828 style C fill:#98971a,stroke:#b8bb26,color:#282828 style D fill:#98971a,stroke:#b8bb26,color:#282828 style E fill:#d79921,stroke:#fabd2f,color:#282828 style F fill:#d79921,stroke:#fabd2f,color:#282828 style G fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style H fill:#d65d0e,stroke:#fe8019,color:#ebdbb2

สูตรคำนวณ Congestion Window:

cwnd new = cwnd old + MSS × MSS cwnd old

โดยที่:

2.1.6 ตัวอย่างโค้ด TCP Socket Programming

"""
ตัวอย่างการสร้าง TCP Server และ Client ด้วย Python
แสดงการทำงานพื้นฐานของโปรโตคอล TCP
"""

import socket
import threading
from datetime import datetime


class TCPServer:
    """
    คลาสสำหรับสร้าง TCP Server
    รองรับการเชื่อมต่อหลายไคลเอนต์พร้อมกัน (Multi-threaded)
    """
    
    def __init__(self, host: str = '127.0.0.1', port: int = 8080):
        """
        กำหนดค่าเริ่มต้นสำหรับ TCP Server
        
        พารามิเตอร์:
            host: ที่อยู่ IP ที่จะรับฟัง (default: localhost)
            port: หมายเลขพอร์ต (default: 8080)
        """
        self.host = host
        self.port = port
        # สร้าง socket แบบ TCP (SOCK_STREAM)
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # อนุญาตให้ใช้พอร์ตซ้ำได้ทันที
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        
    def handle_client(self, client_socket: socket.socket, address: tuple):
        """
        จัดการการสื่อสารกับไคลเอนต์แต่ละราย
        
        พารามิเตอร์:
            client_socket: socket ของไคลเอนต์
            address: (IP, port) ของไคลเอนต์
        """
        print(f"[{datetime.now()}] การเชื่อมต่อจาก {address}")
        
        try:
            while True:
                # รับข้อมูลจากไคลเอนต์ (buffer size = 1024 bytes)
                data = client_socket.recv(1024)
                
                if not data:
                    # ไคลเอนต์ปิดการเชื่อมต่อ
                    break
                    
                message = data.decode('utf-8')
                print(f"[{address}] ได้รับ: {message}")
                
                # ส่งข้อความตอบกลับ
                response = f"เซิร์ฟเวอร์ได้รับ: {message}"
                client_socket.send(response.encode('utf-8'))
                
        except Exception as e:
            print(f"[ข้อผิดพลาด] {address}: {e}")
        finally:
            client_socket.close()
            print(f"[{datetime.now()}] ปิดการเชื่อมต่อจาก {address}")
            
    def start(self):
        """
        เริ่มต้นการทำงานของ TCP Server
        """
        # ผูก socket กับ host และ port
        self.socket.bind((self.host, self.port))
        # เริ่มรับฟังการเชื่อมต่อ (backlog = 5)
        self.socket.listen(5)
        print(f"[TCP Server] กำลังรับฟังที่ {self.host}:{self.port}")
        
        try:
            while True:
                # รอรับการเชื่อมต่อใหม่
                client_socket, address = self.socket.accept()
                # สร้าง thread ใหม่สำหรับไคลเอนต์แต่ละราย
                client_thread = threading.Thread(
                    target=self.handle_client,
                    args=(client_socket, address)
                )
                client_thread.start()
        except KeyboardInterrupt:
            print("\n[TCP Server] กำลังปิดเซิร์ฟเวอร์...")
        finally:
            self.socket.close()


class TCPClient:
    """
    คลาสสำหรับสร้าง TCP Client
    """
    
    def __init__(self, server_host: str = '127.0.0.1', server_port: int = 8080):
        """
        กำหนดค่าเริ่มต้นสำหรับ TCP Client
        
        พารามิเตอร์:
            server_host: ที่อยู่ IP ของเซิร์ฟเวอร์
            server_port: หมายเลขพอร์ตของเซิร์ฟเวอร์
        """
        self.server_host = server_host
        self.server_port = server_port
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        
    def connect(self):
        """
        สร้างการเชื่อมต่อไปยังเซิร์ฟเวอร์ (Three-Way Handshake)
        """
        try:
            self.socket.connect((self.server_host, self.server_port))
            print(f"[TCP Client] เชื่อมต่อกับ {self.server_host}:{self.server_port} สำเร็จ")
            return True
        except Exception as e:
            print(f"[ข้อผิดพลาด] ไม่สามารถเชื่อมต่อได้: {e}")
            return False
            
    def send_message(self, message: str) -> str:
        """
        ส่งข้อความไปยังเซิร์ฟเวอร์และรับการตอบกลับ
        
        พารามิเตอร์:
            message: ข้อความที่ต้องการส่ง
            
        คืนค่า:
            ข้อความตอบกลับจากเซิร์ฟเวอร์
        """
        try:
            # ส่งข้อมูล
            self.socket.send(message.encode('utf-8'))
            # รอรับการตอบกลับ
            response = self.socket.recv(1024)
            return response.decode('utf-8')
        except Exception as e:
            return f"[ข้อผิดพลาด]: {e}"
            
    def close(self):
        """
        ปิดการเชื่อมต่อ (Four-Way Handshake)
        """
        self.socket.close()
        print("[TCP Client] ปิดการเชื่อมต่อแล้ว")


# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1 and sys.argv[1] == 'server':
        # รัน: python tcp_example.py server
        server = TCPServer()
        server.start()
    else:
        # รัน: python tcp_example.py
        client = TCPClient()
        if client.connect():
            # ส่งข้อความทดสอบ
            messages = ["สวัสดี", "ทดสอบ TCP", "ลาก่อน"]
            for msg in messages:
                response = client.send_message(msg)
                print(f"ตอบกลับ: {response}")
            client.close()

ผลลัพธ์การทำงาน:

# เซิร์ฟเวอร์:
[TCP Server] กำลังรับฟังที่ 127.0.0.1:8080
[2024-01-15 10:30:45] การเชื่อมต่อจาก ('127.0.0.1', 54321)
[('127.0.0.1', 54321)] ได้รับ: สวัสดี
[('127.0.0.1', 54321)] ได้รับ: ทดสอบ TCP
[('127.0.0.1', 54321)] ได้รับ: ลาก่อน
[2024-01-15 10:30:46] ปิดการเชื่อมต่อจาก ('127.0.0.1', 54321)

# ไคลเอนต์:
[TCP Client] เชื่อมต่อกับ 127.0.0.1:8080 สำเร็จ
ตอบกลับ: เซิร์ฟเวอร์ได้รับ: สวัสดี
ตอบกลับ: เซิร์ฟเวอร์ได้รับ: ทดสอบ TCP
ตอบกลับ: เซิร์ฟเวอร์ได้รับ: ลาก่อน
[TCP Client] ปิดการเชื่อมต่อแล้ว

2.2 โปรโตคอล UDP (User Datagram Protocol)

2.2.1 ความหมายและคุณสมบัติของ UDP

UDP (User Datagram Protocol) คือโปรโตคอลที่ให้บริการการส่งข้อมูลแบบ ไม่เชื่อมต่อ (Connectionless) และ ไม่รับประกันการส่ง (Unreliable) โดยมีคุณสมบัติหลักดังนี้:

2.2.2 โครงสร้างส่วนหัว UDP (UDP Header Structure)

graph TB
    subgraph UDPHeader["โครงสร้างส่วนหัว UDP (UDP Header) - 8 ไบต์"]
        direction TB
        U1["Source Port (16 บิต) | Destination Port (16 บิต)"]
        U2["Length (16 บิต) | Checksum (16 บิต)"]
        U1 --> U2
    end
    
    style U1 fill:#458588,stroke:#83a598,color:#ebdbb2
    style U2 fill:#d79921,stroke:#fabd2f,color:#282828
ฟิลด์ ขนาด คำอธิบาย
Source Port 16 บิต หมายเลขพอร์ตต้นทาง (optional สามารถเป็น 0)
Destination Port 16 บิต หมายเลขพอร์ตปลายทาง
Length 16 บิต ความยาวรวมของ UDP datagram (header + data)
Checksum 16 บิต ค่าตรวจสอบความถูกต้อง (optional ใน IPv4, บังคับใน IPv6)

2.2.3 การใช้งาน UDP ที่เหมาะสม

UDP เหมาะสำหรับแอปพลิเคชันที่:

แอปพลิเคชัน เหตุผลที่ใช้ UDP
DNS การสอบถามขนาดเล็ก ต้องการความเร็ว
DHCP การกำหนด IP อัตโนมัติ ไม่ต้องการการเชื่อมต่อ
VoIP ส่งเสียงแบบ real-time ยอมรับการสูญหายเล็กน้อย
Video Streaming ส่งวิดีโอต่อเนื่อง ยอมรับการสูญเฟรม
Online Gaming ต้องการ latency ต่ำ
SNMP การจัดการเครือข่าย ข้อความขนาดเล็ก
TFTP โอนไฟล์ง่ายๆ มีกลไก ACK ของตัวเอง

2.2.4 ตัวอย่างโค้ด UDP Socket Programming

"""
ตัวอย่างการสร้าง UDP Server และ Client ด้วย Python
แสดงการทำงานพื้นฐานของโปรโตคอล UDP
"""

import socket
from datetime import datetime


class UDPServer:
    """
    คลาสสำหรับสร้าง UDP Server
    รับและตอบกลับ datagram จากหลายไคลเอนต์
    """
    
    def __init__(self, host: str = '127.0.0.1', port: int = 9090):
        """
        กำหนดค่าเริ่มต้นสำหรับ UDP Server
        
        พารามิเตอร์:
            host: ที่อยู่ IP ที่จะรับฟัง
            port: หมายเลขพอร์ต
        """
        self.host = host
        self.port = port
        # สร้าง socket แบบ UDP (SOCK_DGRAM)
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        
    def start(self):
        """
        เริ่มต้นการทำงานของ UDP Server
        """
        # ผูก socket กับ host และ port
        self.socket.bind((self.host, self.port))
        print(f"[UDP Server] กำลังรับฟังที่ {self.host}:{self.port}")
        
        try:
            while True:
                # รับ datagram และที่อยู่ของผู้ส่ง
                # UDP ไม่ต้อง accept() เพราะไม่มีการเชื่อมต่อ
                data, client_address = self.socket.recvfrom(1024)
                
                message = data.decode('utf-8')
                print(f"[{datetime.now()}] จาก {client_address}: {message}")
                
                # ส่งข้อความตอบกลับไปยังผู้ส่ง
                response = f"ได้รับ: {message}"
                self.socket.sendto(response.encode('utf-8'), client_address)
                
        except KeyboardInterrupt:
            print("\n[UDP Server] กำลังปิดเซิร์ฟเวอร์...")
        finally:
            self.socket.close()


class UDPClient:
    """
    คลาสสำหรับสร้าง UDP Client
    """
    
    def __init__(self, server_host: str = '127.0.0.1', server_port: int = 9090):
        """
        กำหนดค่าเริ่มต้นสำหรับ UDP Client
        
        พารามิเตอร์:
            server_host: ที่อยู่ IP ของเซิร์ฟเวอร์
            server_port: หมายเลขพอร์ตของเซิร์ฟเวอร์
        """
        self.server_address = (server_host, server_port)
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        # กำหนด timeout เพื่อป้องกันการรอไม่สิ้นสุด
        self.socket.settimeout(5.0)
        
    def send_message(self, message: str) -> str:
        """
        ส่งข้อความไปยังเซิร์ฟเวอร์และรอรับการตอบกลับ
        
        พารามิเตอร์:
            message: ข้อความที่ต้องการส่ง
            
        คืนค่า:
            ข้อความตอบกลับจากเซิร์ฟเวอร์ หรือข้อความแจ้งเตือน
        """
        try:
            # ส่ง datagram ไปยังเซิร์ฟเวอร์
            # UDP ไม่ต้อง connect() เพราะไม่มีการเชื่อมต่อ
            self.socket.sendto(message.encode('utf-8'), self.server_address)
            
            # รอรับการตอบกลับ
            data, server = self.socket.recvfrom(1024)
            return data.decode('utf-8')
            
        except socket.timeout:
            return "[หมดเวลา] ไม่ได้รับการตอบกลับจากเซิร์ฟเวอร์"
        except Exception as e:
            return f"[ข้อผิดพลาด]: {e}"
            
    def close(self):
        """
        ปิด socket (UDP ไม่มี graceful shutdown)
        """
        self.socket.close()
        print("[UDP Client] ปิด socket แล้ว")


def measure_latency(client: UDPClient, iterations: int = 10) -> dict:
    """
    วัดค่า latency ของการส่งข้อมูล UDP
    
    พารามิเตอร์:
        client: UDP client object
        iterations: จำนวนครั้งที่ทดสอบ
        
    คืนค่า:
        dictionary ที่มีค่าสถิติ latency
    """
    import time
    
    latencies = []
    
    for i in range(iterations):
        start_time = time.time()
        response = client.send_message(f"ping-{i}")
        end_time = time.time()
        
        if not response.startswith("["):
            latency = (end_time - start_time) * 1000  # แปลงเป็น ms
            latencies.append(latency)
            
    if latencies:
        return {
            'min': min(latencies),
            'max': max(latencies),
            'avg': sum(latencies) / len(latencies),
            'success_rate': len(latencies) / iterations * 100
        }
    return {'error': 'ไม่สามารถวัดค่า latency ได้'}


# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    import sys
    
    if len(sys.argv) > 1 and sys.argv[1] == 'server':
        # รัน: python udp_example.py server
        server = UDPServer()
        server.start()
    else:
        # รัน: python udp_example.py
        client = UDPClient()
        
        # ส่งข้อความทดสอบ
        messages = ["สวัสดี UDP", "ทดสอบ Datagram", "ข้อมูล real-time"]
        for msg in messages:
            response = client.send_message(msg)
            print(f"ตอบกลับ: {response}")
        
        # วัด latency
        print("\n--- ผลการวัด Latency ---")
        stats = measure_latency(client, 10)
        if 'error' not in stats:
            print(f"ต่ำสุด: {stats['min']:.2f} ms")
            print(f"สูงสุด: {stats['max']:.2f} ms")
            print(f"เฉลี่ย: {stats['avg']:.2f} ms")
            print(f"อัตราสำเร็จ: {stats['success_rate']:.1f}%")
        
        client.close()

2.3 การเปรียบเทียบ TCP และ UDP

คุณสมบัติ TCP UDP
ประเภทการเชื่อมต่อ Connection-oriented Connectionless
ความน่าเชื่อถือ รับประกันการส่ง ไม่รับประกัน
การเรียงลำดับ รับประกันลำดับ ไม่รับประกัน
ขนาดส่วนหัว 20-60 bytes 8 bytes
Flow Control มี (Sliding Window) ไม่มี
Congestion Control มี ไม่มี
ความเร็ว ช้ากว่า เร็วกว่า
Overhead สูง ต่ำ
Broadcast/Multicast ไม่รองรับ รองรับ
ตัวอย่างการใช้งาน HTTP, FTP, SMTP, SSH DNS, DHCP, VoIP, Gaming
graph LR
    subgraph TCP_Flow["การทำงานของ TCP"]
        T1["สร้างการเชื่อมต่อ
(3-Way Handshake)"] T2["ส่งข้อมูล"] T3["รอ ACK"] T4["ส่งซ้ำ
(ถ้าไม่ได้ ACK)"] T5["ปิดการเชื่อมต่อ
(4-Way Handshake)"] T1 --> T2 --> T3 --> T4 T3 --> T5 end subgraph UDP_Flow["การทำงานของ UDP"] U1["ส่ง Datagram"] U2["จบ"] U1 --> U2 end style T1 fill:#458588,stroke:#83a598,color:#ebdbb2 style T2 fill:#98971a,stroke:#b8bb26,color:#282828 style T3 fill:#d79921,stroke:#fabd2f,color:#282828 style T4 fill:#d65d0e,stroke:#fe8019,color:#ebdbb2 style T5 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style U1 fill:#98971a,stroke:#b8bb26,color:#282828 style U2 fill:#458588,stroke:#83a598,color:#ebdbb2

3. โปรโตคอลชั้นเครือข่าย (Network Layer Protocols)

ชั้นเครือข่าย (Network Layer) รับผิดชอบการส่งข้อมูลระหว่างโฮสต์ (Host-to-Host Communication) ข้ามเครือข่ายต่างๆ โดยใช้การกำหนดที่อยู่แบบ Logical (IP Address) และการจัดเส้นทาง (Routing)

3.1 โปรโตคอล IPv4 (Internet Protocol version 4)

3.1.1 ความหมายและคุณสมบัติของ IPv4

IPv4 (Internet Protocol version 4) คือโปรโตคอลหลักในการส่งข้อมูลระดับเครือข่าย ถูกกำหนดใน RFC 791 (1981) มีคุณสมบัติหลักดังนี้:

3.1.2 โครงสร้างส่วนหัว IPv4 (IPv4 Header Structure)

graph TB
    subgraph IPv4Header["โครงสร้างส่วนหัว IPv4 - 20-60 ไบต์"]
        direction TB
        I1["Version (4) | IHL (4) | Type of Service (8) | Total Length (16)"]
        I2["Identification (16) | Flags (3) | Fragment Offset (13)"]
        I3["Time to Live (8) | Protocol (8) | Header Checksum (16)"]
        I4["Source IP Address (32 บิต)"]
        I5["Destination IP Address (32 บิต)"]
        I6["Options (ถ้ามี) | Padding"]
        I1 --> I2 --> I3 --> I4 --> I5 --> I6
    end
    
    style I1 fill:#458588,stroke:#83a598,color:#ebdbb2
    style I2 fill:#d79921,stroke:#fabd2f,color:#282828
    style I3 fill:#98971a,stroke:#b8bb26,color:#282828
    style I4 fill:#d65d0e,stroke:#fe8019,color:#ebdbb2
    style I5 fill:#d65d0e,stroke:#fe8019,color:#ebdbb2
    style I6 fill:#b16286,stroke:#d3869b,color:#ebdbb2
ฟิลด์ ขนาด (บิต) คำอธิบาย
Version 4 เวอร์ชันของ IP (4 สำหรับ IPv4)
IHL (Internet Header Length) 4 ความยาวของส่วนหัว (หน่วยเป็น 32-bit words)
Type of Service (ToS) 8 ระบุความสำคัญและประเภทบริการ
Total Length 16 ความยาวรวมของแพ็กเก็ต (bytes)
Identification 16 ใช้ระบุ fragments ของแพ็กเก็ตเดียวกัน
Flags 3 ธงควบคุมการแบ่ง fragment
Fragment Offset 13 ตำแหน่งของ fragment ในแพ็กเก็ตต้นฉบับ
TTL (Time to Live) 8 จำนวน hop สูงสุดก่อนถูกทิ้ง
Protocol 8 โปรโตคอลชั้นบน (6=TCP, 17=UDP, 1=ICMP)
Header Checksum 16 ค่าตรวจสอบความถูกต้องของส่วนหัว
Source IP 32 ที่อยู่ IP ต้นทาง
Destination IP 32 ที่อยู่ IP ปลายทาง

3.1.3 การแบ่งคลาสที่อยู่ IPv4 (IPv4 Address Classes)

3.1.3.1 ความเป็นมาของระบบ Classful Addressing

ระบบ Classful Addressing ถูกกำหนดขึ้นในปี 1981 ตาม RFC 791 เพื่อจัดสรรที่อยู่ IP ให้กับองค์กรต่างๆ อย่างเป็นระบบ โดยแบ่งที่อยู่ IP ออกเป็น 5 คลาส (Class A ถึง Class E) ตามบิตแรกๆ ของที่อยู่

หลักการพื้นฐาน:

graph TB
    subgraph IPv4Structure["โครงสร้างที่อยู่ IPv4 (32 บิต)"]
        direction LR
        O1["Octet 1
8 บิต
(0-255)"] DOT1["."] O2["Octet 2
8 บิต
(0-255)"] DOT2["."] O3["Octet 3
8 บิต
(0-255)"] DOT3["."] O4["Octet 4
8 บิต
(0-255)"] O1 --- DOT1 --- O2 --- DOT2 --- O3 --- DOT3 --- O4 end subgraph Example["ตัวอย่าง: 192.168.1.100"] E1["192
11000000"] ED1["."] E2["168
10101000"] ED2["."] E3["1
00000001"] ED3["."] E4["100
01100100"] E1 --- ED1 --- E2 --- ED2 --- E3 --- ED3 --- E4 end IPv4Structure --> Example style O1 fill:#458588,stroke:#83a598,color:#ebdbb2 style O2 fill:#458588,stroke:#83a598,color:#ebdbb2 style O3 fill:#458588,stroke:#83a598,color:#ebdbb2 style O4 fill:#458588,stroke:#83a598,color:#ebdbb2 style E1 fill:#98971a,stroke:#b8bb26,color:#282828 style E2 fill:#98971a,stroke:#b8bb26,color:#282828 style E3 fill:#d79921,stroke:#fabd2f,color:#282828 style E4 fill:#d79921,stroke:#fabd2f,color:#282828

3.1.3.2 Class A - เครือข่ายขนาดใหญ่มาก

Class A ถูกออกแบบสำหรับองค์กรขนาดใหญ่มากที่ต้องการที่อยู่ IP จำนวนมหาศาล

graph TB
    subgraph ClassADetail["Class A - รายละเอียด"]
        direction TB
        
        subgraph BitPattern["รูปแบบบิต"]
            BP["0xxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx"]
            BP_DESC["บิตแรก = 0 (ระบุว่าเป็น Class A)"]
        end
        
        subgraph Structure["โครงสร้าง"]
            NET["Network ID
8 บิต (1 ออกเตต)"] HOST["Host ID
24 บิต (3 ออกเตต)"] NET --> HOST end subgraph Range["ช่วงที่อยู่"] R1["เริ่มต้น: 1.0.0.0"] R2["สิ้นสุด: 126.255.255.255"] R3["ยกเว้น: 0.x.x.x และ 127.x.x.x"] end subgraph Subnet["Subnet Mask"] SM["255.0.0.0"] SM_BIN["11111111.00000000.00000000.00000000"] SM_CIDR["/8"] end end style BP fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style NET fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style HOST fill:#d65d0e,stroke:#fe8019,color:#ebdbb2 style SM fill:#458588,stroke:#83a598,color:#ebdbb2

คุณสมบัติ Class A:

คุณสมบัติ ค่า คำอธิบาย
บิตแรก 0 ระบุว่าเป็น Class A
ช่วง Octet แรก 1-126 0 และ 127 สงวนไว้
Default Subnet Mask 255.0.0.0 /8 ใน CIDR notation
จำนวน Network 126 2⁷ - 2 (ลบ 0 และ 127)
จำนวน Host ต่อ Network 16,777,214 2²⁴ - 2
ผู้ใช้งาน รัฐบาล, องค์กรขนาดใหญ่มาก เช่น Apple, MIT, US DoD

สูตรคำนวณจำนวน Host สำหรับ Class A:

จำนวน Host = 2 24 - 2 = 16,777,216 - 2 = 16,777,214

โดยที่:

ตัวอย่างที่อยู่ Class A:

ที่อยู่ IP Network ID Host ID ประเภท
10.0.0.0 10 0.0.0 Network Address
10.0.0.1 10 0.0.1 Host Address แรก
10.255.255.254 10 255.255.254 Host Address สุดท้าย
10.255.255.255 10 255.255.255 Broadcast Address
8.8.8.8 8 8.8.8 Google DNS
17.0.0.1 17 0.0.1 Apple Network

3.1.3.3 Class B - เครือข่ายขนาดกลาง

Class B ถูกออกแบบสำหรับองค์กรขนาดกลางถึงขนาดใหญ่

graph TB
    subgraph ClassBDetail["Class B - รายละเอียด"]
        direction TB
        
        subgraph BitPattern["รูปแบบบิต"]
            BP["10xxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx"]
            BP_DESC["2 บิตแรก = 10 (ระบุว่าเป็น Class B)"]
        end
        
        subgraph Structure["โครงสร้าง"]
            NET["Network ID
16 บิต (2 ออกเตต)"] HOST["Host ID
16 บิต (2 ออกเตต)"] NET --> HOST end subgraph Range["ช่วงที่อยู่"] R1["เริ่มต้น: 128.0.0.0"] R2["สิ้นสุด: 191.255.255.255"] end subgraph Subnet["Subnet Mask"] SM["255.255.0.0"] SM_BIN["11111111.11111111.00000000.00000000"] SM_CIDR["/16"] end end style BP fill:#d79921,stroke:#fabd2f,color:#282828 style NET fill:#d79921,stroke:#fabd2f,color:#282828 style HOST fill:#d65d0e,stroke:#fe8019,color:#ebdbb2 style SM fill:#458588,stroke:#83a598,color:#ebdbb2

คุณสมบัติ Class B:

คุณสมบัติ ค่า คำอธิบาย
2 บิตแรก 10 ระบุว่าเป็น Class B
ช่วง Octet แรก 128-191 ค่าที่ขึ้นต้นด้วย 10xxxxxx
Default Subnet Mask 255.255.0.0 /16 ใน CIDR notation
จำนวน Network 16,384 2¹⁴
จำนวน Host ต่อ Network 65,534 2¹⁶ - 2
ผู้ใช้งาน มหาวิทยาลัย, บริษัทขนาดใหญ่ เช่น Microsoft, IBM

สูตรคำนวณจำนวน Network สำหรับ Class B:

จำนวน Network = 2 14 = 16,384

โดยที่:

สูตรคำนวณจำนวน Host สำหรับ Class B:

จำนวน Host = 2 16 - 2 = 65,536 - 2 = 65,534

ตัวอย่างที่อยู่ Class B:

ที่อยู่ IP Network ID Host ID ประเภท
172.16.0.0 172.16 0.0 Network Address (Private)
172.16.0.1 172.16 0.1 Host Address แรก
172.16.255.254 172.16 255.254 Host Address สุดท้าย
172.16.255.255 172.16 255.255 Broadcast Address
128.0.0.1 128.0 0.1 Class B แรก
191.255.0.1 191.255 0.1 Class B สุดท้าย

3.1.3.4 Class C - เครือข่ายขนาดเล็ก

Class C ถูกออกแบบสำหรับองค์กรขนาดเล็กที่ต้องการที่อยู่ IP จำนวนไม่มาก

graph TB
    subgraph ClassCDetail["Class C - รายละเอียด"]
        direction TB
        
        subgraph BitPattern["รูปแบบบิต"]
            BP["110xxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx"]
            BP_DESC["3 บิตแรก = 110 (ระบุว่าเป็น Class C)"]
        end
        
        subgraph Structure["โครงสร้าง"]
            NET["Network ID
24 บิต (3 ออกเตต)"] HOST["Host ID
8 บิต (1 ออกเตต)"] NET --> HOST end subgraph Range["ช่วงที่อยู่"] R1["เริ่มต้น: 192.0.0.0"] R2["สิ้นสุด: 223.255.255.255"] end subgraph Subnet["Subnet Mask"] SM["255.255.255.0"] SM_BIN["11111111.11111111.11111111.00000000"] SM_CIDR["/24"] end end style BP fill:#98971a,stroke:#b8bb26,color:#282828 style NET fill:#98971a,stroke:#b8bb26,color:#282828 style HOST fill:#d65d0e,stroke:#fe8019,color:#ebdbb2 style SM fill:#458588,stroke:#83a598,color:#ebdbb2

คุณสมบัติ Class C:

คุณสมบัติ ค่า คำอธิบาย
3 บิตแรก 110 ระบุว่าเป็น Class C
ช่วง Octet แรก 192-223 ค่าที่ขึ้นต้นด้วย 110xxxxx
Default Subnet Mask 255.255.255.0 /24 ใน CIDR notation
จำนวน Network 2,097,152 2²¹
จำนวน Host ต่อ Network 254 2⁸ - 2
ผู้ใช้งาน SME, สำนักงานขนาดเล็ก เครือข่ายส่วนใหญ่ในปัจจุบัน

สูตรคำนวณจำนวน Network สำหรับ Class C:

จำนวน Network = 2 21 = 2,097,152

สูตรคำนวณจำนวน Host สำหรับ Class C:

จำนวน Host = 2 8 - 2 = 256 - 2 = 254

ตัวอย่างที่อยู่ Class C:

ที่อยู่ IP Network ID Host ID ประเภท
192.168.1.0 192.168.1 0 Network Address (Private)
192.168.1.1 192.168.1 1 Host Address แรก (มักเป็น Gateway)
192.168.1.254 192.168.1 254 Host Address สุดท้าย
192.168.1.255 192.168.1 255 Broadcast Address
203.0.113.50 203.0.113 50 Documentation Range

3.1.3.5 Class D และ Class E - คลาสพิเศษ
graph TB
    subgraph SpecialClasses["Class D และ Class E"]
        direction TB
        
        subgraph ClassD["Class D - Multicast"]
            D1["1110xxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx"]
            D2["224.0.0.0 - 239.255.255.255"]
            D3["ใช้สำหรับ Multicast Groups"]
            D4["ไม่มี Network/Host แยก"]
        end
        
        subgraph ClassE["Class E - Reserved"]
            E1["1111xxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx"]
            E2["240.0.0.0 - 255.255.255.255"]
            E3["สงวนไว้สำหรับการทดลอง"]
            E4["ไม่ใช้ในการทำงานจริง"]
        end
    end
    
    style D1 fill:#b16286,stroke:#d3869b,color:#ebdbb2
    style D2 fill:#b16286,stroke:#d3869b,color:#ebdbb2
    style D3 fill:#b16286,stroke:#d3869b,color:#ebdbb2
    style D4 fill:#b16286,stroke:#d3869b,color:#ebdbb2
    style E1 fill:#928374,stroke:#a89984,color:#ebdbb2
    style E2 fill:#928374,stroke:#a89984,color:#ebdbb2
    style E3 fill:#928374,stroke:#a89984,color:#ebdbb2
    style E4 fill:#928374,stroke:#a89984,color:#ebdbb2

Class D - Multicast:

คุณสมบัติ ค่า
4 บิตแรก 1110
ช่วงที่อยู่ 224.0.0.0 - 239.255.255.255
วัตถุประสงค์ ส่งข้อมูลไปยังกลุ่มของโฮสต์พร้อมกัน
Subnet Mask ไม่มี (ไม่แบ่ง Network/Host)

ที่อยู่ Multicast ที่สำคัญ:

ที่อยู่ ชื่อ คำอธิบาย
224.0.0.1 All Hosts ทุกโฮสต์ใน local network
224.0.0.2 All Routers ทุกเราเตอร์ใน local network
224.0.0.5 OSPF Routers เราเตอร์ที่ใช้ OSPF
224.0.0.6 OSPF DR OSPF Designated Routers
224.0.0.9 RIPv2 RIP version 2
224.0.0.251 mDNS Multicast DNS
224.0.1.1 NTP Network Time Protocol
239.255.255.250 SSDP Simple Service Discovery

Class E - Reserved:

คุณสมบัติ ค่า
4 บิตแรก 1111
ช่วงที่อยู่ 240.0.0.0 - 255.255.255.254
วัตถุประสงค์ สงวนไว้สำหรับการวิจัยและทดลอง
สถานะ ไม่สามารถใช้งานบนอินเทอร์เน็ตสาธารณะ

หมายเหตุ: 255.255.255.255 เป็น Limited Broadcast Address ซึ่งใช้ส่ง broadcast ไปยังทุกโฮสต์ในเครือข่ายท้องถิ่น


3.1.3.6 ตารางเปรียบเทียบทุก Class
คุณสมบัติ Class A Class B Class C Class D Class E
บิตนำหน้า 0 10 110 1110 1111
Octet แรก 1-126 128-191 192-223 224-239 240-255
Default Mask /8 /16 /24 N/A N/A
Network bits 8 16 24 N/A N/A
Host bits 24 16 8 N/A N/A
จำนวน Networks 126 16,384 2,097,152 N/A N/A
Hosts/Network 16,777,214 65,534 254 N/A N/A
การใช้งาน องค์กรยักษ์ใหญ่ องค์กรขนาดใหญ่ องค์กรทั่วไป Multicast วิจัย
graph LR
    subgraph AddressSpace["พื้นที่ที่อยู่ IPv4 ทั้งหมด (0-255)"]
        direction LR
        A["Class A
1-126
50%"] B["Class B
128-191
25%"] C["Class C
192-223
12.5%"] D["Class D
224-239
6.25%"] E["Class E
240-255
6.25%"] A --> B --> C --> D --> E end style A fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style B fill:#d79921,stroke:#fabd2f,color:#282828 style C fill:#98971a,stroke:#b8bb26,color:#282828 style D fill:#b16286,stroke:#d3869b,color:#ebdbb2 style E fill:#928374,stroke:#a89984,color:#ebdbb2

3.1.3.7 ที่อยู่พิเศษและที่อยู่สงวน
graph TB
    subgraph SpecialAddresses["ที่อยู่ IPv4 พิเศษ"]
        direction TB
        
        subgraph Private["Private Address Ranges (RFC 1918)"]
            P1["10.0.0.0/8
Class A Private
16.7 ล้านที่อยู่"] P2["172.16.0.0/12
Class B Private
1 ล้านที่อยู่"] P3["192.168.0.0/16
Class C Private
65,536 ที่อยู่"] end subgraph Loopback["Loopback"] L1["127.0.0.0/8
ทดสอบภายในเครื่อง
127.0.0.1 = localhost"] end subgraph LinkLocal["Link-Local (APIPA)"] LL1["169.254.0.0/16
กำหนดอัตโนมัติ
เมื่อไม่มี DHCP"] end subgraph Documentation["Documentation"] DOC1["192.0.2.0/24 (TEST-NET-1)"] DOC2["198.51.100.0/24 (TEST-NET-2)"] DOC3["203.0.113.0/24 (TEST-NET-3)"] end end style P1 fill:#458588,stroke:#83a598,color:#ebdbb2 style P2 fill:#458588,stroke:#83a598,color:#ebdbb2 style P3 fill:#458588,stroke:#83a598,color:#ebdbb2 style L1 fill:#98971a,stroke:#b8bb26,color:#282828 style LL1 fill:#d79921,stroke:#fabd2f,color:#282828 style DOC1 fill:#b16286,stroke:#d3869b,color:#ebdbb2 style DOC2 fill:#b16286,stroke:#d3869b,color:#ebdbb2 style DOC3 fill:#b16286,stroke:#d3869b,color:#ebdbb2

ตารางที่อยู่พิเศษทั้งหมด:

ช่วงที่อยู่ ชื่อ RFC คำอธิบาย
0.0.0.0/8 This Network RFC 1122 ระบุเครือข่ายปัจจุบัน
10.0.0.0/8 Private-Use RFC 1918 เครือข่ายส่วนตัว Class A
100.64.0.0/10 Shared Address RFC 6598 Carrier-Grade NAT
127.0.0.0/8 Loopback RFC 1122 ทดสอบภายในเครื่อง
169.254.0.0/16 Link-Local RFC 3927 APIPA
172.16.0.0/12 Private-Use RFC 1918 เครือข่ายส่วนตัว Class B
192.0.0.0/24 IETF Protocol RFC 6890 IETF Protocol Assignments
192.0.2.0/24 Documentation RFC 5737 TEST-NET-1
192.88.99.0/24 6to4 Relay RFC 3068 IPv6 to IPv4 relay
192.168.0.0/16 Private-Use RFC 1918 เครือข่ายส่วนตัว Class C
198.18.0.0/15 Benchmarking RFC 2544 ทดสอบประสิทธิภาพ
198.51.100.0/24 Documentation RFC 5737 TEST-NET-2
203.0.113.0/24 Documentation RFC 5737 TEST-NET-3
224.0.0.0/4 Multicast RFC 5771 Class D Multicast
240.0.0.0/4 Reserved RFC 1112 Class E Reserved
255.255.255.255/32 Limited Broadcast RFC 919 Broadcast ทุกเครื่องใน LAN

3.1.3.8 ตัวอย่างโค้ดวิเคราะห์ที่อยู่ IPv4
"""
โมดูลวิเคราะห์ที่อยู่ IPv4 และ Class
แสดงการระบุ Class, Network ID, Host ID และคุณสมบัติต่างๆ
"""

from dataclasses import dataclass
from typing import Optional, Tuple
from enum import Enum


class IPClass(Enum):
    """
    Enum สำหรับ Class ของที่อยู่ IPv4
    """
    CLASS_A = "A"
    CLASS_B = "B"
    CLASS_C = "C"
    CLASS_D = "D"  # Multicast
    CLASS_E = "E"  # Reserved
    SPECIAL = "Special"  # ที่อยู่พิเศษ


@dataclass
class IPv4Analysis:
    """
    คลาสเก็บผลการวิเคราะห์ที่อยู่ IPv4
    """
    ip_address: str           # ที่อยู่ IP
    ip_binary: str            # รูปแบบ binary
    ip_class: IPClass         # Class ของ IP
    default_subnet_mask: str  # Subnet mask ปกติ
    network_id: str           # Network ID
    host_id: str              # Host ID
    network_bits: int         # จำนวนบิต Network
    host_bits: int            # จำนวนบิต Host
    max_hosts: int            # จำนวน host สูงสุด
    is_private: bool          # เป็นที่อยู่ private หรือไม่
    is_loopback: bool         # เป็น loopback หรือไม่
    is_multicast: bool        # เป็น multicast หรือไม่
    special_purpose: Optional[str] = None  # วัตถุประสงค์พิเศษ


def ip_to_binary(ip: str) -> str:
    """
    แปลงที่อยู่ IP เป็น binary string
    
    พารามิเตอร์:
        ip: ที่อยู่ IP ในรูปแบบ dotted decimal
        
    คืนค่า:
        binary string คั่นด้วยจุด
        
    ตัวอย่าง:
        >>> ip_to_binary("192.168.1.1")
        '11000000.10101000.00000001.00000001'
    """
    octets = ip.split('.')
    binary_octets = [format(int(octet), '08b') for octet in octets]
    return '.'.join(binary_octets)


def binary_to_ip(binary: str) -> str:
    """
    แปลง binary string เป็นที่อยู่ IP
    
    พารามิเตอร์:
        binary: binary string (มีหรือไม่มีจุดก็ได้)
        
    คืนค่า:
        ที่อยู่ IP ในรูปแบบ dotted decimal
    """
    # ลบจุดออก
    binary_clean = binary.replace('.', '')
    
    # แบ่งเป็น 4 ส่วน
    octets = [binary_clean[i:i+8] for i in range(0, 32, 8)]
    decimal_octets = [str(int(octet, 2)) for octet in octets]
    
    return '.'.join(decimal_octets)


def determine_class(first_octet: int) -> Tuple[IPClass, int, int, str]:
    """
    ระบุ Class จาก octet แรก
    
    พารามิเตอร์:
        first_octet: ค่า octet แรก (0-255)
        
    คืนค่า:
        tuple ของ (IPClass, network_bits, host_bits, default_mask)
    """
    if first_octet == 0:
        return (IPClass.SPECIAL, 0, 0, "N/A")
    elif first_octet == 127:
        return (IPClass.SPECIAL, 8, 24, "255.0.0.0")
    elif 1 <= first_octet <= 126:
        return (IPClass.CLASS_A, 8, 24, "255.0.0.0")
    elif 128 <= first_octet <= 191:
        return (IPClass.CLASS_B, 16, 16, "255.255.0.0")
    elif 192 <= first_octet <= 223:
        return (IPClass.CLASS_C, 24, 8, "255.255.255.0")
    elif 224 <= first_octet <= 239:
        return (IPClass.CLASS_D, 0, 0, "N/A")
    elif 240 <= first_octet <= 255:
        return (IPClass.CLASS_E, 0, 0, "N/A")
    else:
        return (IPClass.SPECIAL, 0, 0, "N/A")


def check_special_purpose(ip: str) -> Optional[str]:
    """
    ตรวจสอบว่าที่อยู่ IP มีวัตถุประสงค์พิเศษหรือไม่
    
    พารามิเตอร์:
        ip: ที่อยู่ IP
        
    คืนค่า:
        คำอธิบายวัตถุประสงค์พิเศษ หรือ None
    """
    octets = [int(x) for x in ip.split('.')]
    first = octets[0]
    
    # ตรวจสอบ Private Addresses
    if first == 10:
        return "Private Address (10.0.0.0/8)"
    if first == 172 and 16 <= octets[1] <= 31:
        return "Private Address (172.16.0.0/12)"
    if first == 192 and octets[1] == 168:
        return "Private Address (192.168.0.0/16)"
    
    # ตรวจสอบ Loopback
    if first == 127:
        return "Loopback Address (127.0.0.0/8)"
    
    # ตรวจสอบ Link-Local
    if first == 169 and octets[1] == 254:
        return "Link-Local / APIPA (169.254.0.0/16)"
    
    # ตรวจสอบ Documentation
    if first == 192 and octets[1] == 0 and octets[2] == 2:
        return "Documentation (TEST-NET-1)"
    if first == 198 and octets[1] == 51 and octets[2] == 100:
        return "Documentation (TEST-NET-2)"
    if first == 203 and octets[1] == 0 and octets[2] == 113:
        return "Documentation (TEST-NET-3)"
    
    # ตรวจสอบ Carrier-Grade NAT
    if first == 100 and 64 <= octets[1] <= 127:
        return "Shared Address Space / CGNAT (100.64.0.0/10)"
    
    # ตรวจสอบ Benchmarking
    if first == 198 and octets[1] in [18, 19]:
        return "Benchmarking (198.18.0.0/15)"
    
    # ตรวจสอบ Multicast
    if 224 <= first <= 239:
        return "Multicast Address"
    
    # ตรวจสอบ Reserved
    if 240 <= first <= 255:
        return "Reserved for Future Use"
    
    # ตรวจสอบ Broadcast
    if ip == "255.255.255.255":
        return "Limited Broadcast"
    
    return None


def get_network_and_host_id(ip: str, ip_class: IPClass) -> Tuple[str, str]:
    """
    แยก Network ID และ Host ID
    
    พารามิเตอร์:
        ip: ที่อยู่ IP
        ip_class: Class ของ IP
        
    คืนค่า:
        tuple ของ (network_id, host_id)
    """
    octets = ip.split('.')
    
    if ip_class == IPClass.CLASS_A:
        network_id = octets[0]
        host_id = '.'.join(octets[1:])
    elif ip_class == IPClass.CLASS_B:
        network_id = '.'.join(octets[:2])
        host_id = '.'.join(octets[2:])
    elif ip_class == IPClass.CLASS_C:
        network_id = '.'.join(octets[:3])
        host_id = octets[3]
    else:
        network_id = ip
        host_id = "N/A"
    
    return network_id, host_id


def analyze_ipv4(ip: str) -> IPv4Analysis:
    """
    วิเคราะห์ที่อยู่ IPv4 อย่างละเอียด
    
    พารามิเตอร์:
        ip: ที่อยู่ IP ในรูปแบบ dotted decimal
        
    คืนค่า:
        IPv4Analysis object ที่มีข้อมูลครบถ้วน
        
    ตัวอย่าง:
        >>> result = analyze_ipv4("192.168.1.100")
        >>> print(result.ip_class)
        IPClass.CLASS_C
    """
    # แยก octets
    octets = [int(x) for x in ip.split('.')]
    first_octet = octets[0]
    
    # แปลงเป็น binary
    ip_binary = ip_to_binary(ip)
    
    # ระบุ Class
    ip_class, network_bits, host_bits, default_mask = determine_class(first_octet)
    
    # แยก Network ID และ Host ID
    network_id, host_id = get_network_and_host_id(ip, ip_class)
    
    # คำนวณจำนวน host สูงสุด
    max_hosts = (2 ** host_bits - 2) if host_bits > 0 else 0
    
    # ตรวจสอบประเภทพิเศษ
    special_purpose = check_special_purpose(ip)
    is_private = "Private" in (special_purpose or "")
    is_loopback = first_octet == 127
    is_multicast = 224 <= first_octet <= 239
    
    return IPv4Analysis(
        ip_address=ip,
        ip_binary=ip_binary,
        ip_class=ip_class,
        default_subnet_mask=default_mask,
        network_id=network_id,
        host_id=host_id,
        network_bits=network_bits,
        host_bits=host_bits,
        max_hosts=max_hosts,
        is_private=is_private,
        is_loopback=is_loopback,
        is_multicast=is_multicast,
        special_purpose=special_purpose
    )


def calculate_network_range(ip: str, ip_class: IPClass) -> Tuple[str, str, str]:
    """
    คำนวณช่วง Network Address, First Host, Last Host, Broadcast
    
    พารามิเตอร์:
        ip: ที่อยู่ IP
        ip_class: Class ของ IP
        
    คืนค่า:
        tuple ของ (network_address, first_host, last_host, broadcast)
    """
    octets = [int(x) for x in ip.split('.')]
    
    if ip_class == IPClass.CLASS_A:
        network = f"{octets[0]}.0.0.0"
        first_host = f"{octets[0]}.0.0.1"
        last_host = f"{octets[0]}.255.255.254"
        broadcast = f"{octets[0]}.255.255.255"
    elif ip_class == IPClass.CLASS_B:
        network = f"{octets[0]}.{octets[1]}.0.0"
        first_host = f"{octets[0]}.{octets[1]}.0.1"
        last_host = f"{octets[0]}.{octets[1]}.255.254"
        broadcast = f"{octets[0]}.{octets[1]}.255.255"
    elif ip_class == IPClass.CLASS_C:
        network = f"{octets[0]}.{octets[1]}.{octets[2]}.0"
        first_host = f"{octets[0]}.{octets[1]}.{octets[2]}.1"
        last_host = f"{octets[0]}.{octets[1]}.{octets[2]}.254"
        broadcast = f"{octets[0]}.{octets[1]}.{octets[2]}.255"
    else:
        return (ip, "N/A", "N/A", "N/A")
    
    return (network, first_host, last_host, broadcast)


def print_analysis_report(analysis: IPv4Analysis):
    """
    พิมพ์รายงานการวิเคราะห์
    
    พารามิเตอร์:
        analysis: ผลการวิเคราะห์
    """
    print("=" * 60)
    print(f"รายงานการวิเคราะห์ที่อยู่ IPv4: {analysis.ip_address}")
    print("=" * 60)
    
    print(f"\n📍 ข้อมูลพื้นฐาน:")
    print(f"   ที่อยู่ IP:        {analysis.ip_address}")
    print(f"   Binary:           {analysis.ip_binary}")
    print(f"   Class:            {analysis.ip_class.value}")
    
    if analysis.ip_class in [IPClass.CLASS_A, IPClass.CLASS_B, IPClass.CLASS_C]:
        print(f"\n🔢 โครงสร้างที่อยู่:")
        print(f"   Default Mask:     {analysis.default_subnet_mask}")
        print(f"   Network ID:       {analysis.network_id}")
        print(f"   Host ID:          {analysis.host_id}")
        print(f"   Network Bits:     {analysis.network_bits}")
        print(f"   Host Bits:        {analysis.host_bits}")
        print(f"   Max Hosts:        {analysis.max_hosts:,}")
        
        # คำนวณช่วงเครือข่าย
        network, first, last, broadcast = calculate_network_range(
            analysis.ip_address, analysis.ip_class
        )
        print(f"\n📊 ช่วงเครือข่าย:")
        print(f"   Network Address:  {network}")
        print(f"   First Host:       {first}")
        print(f"   Last Host:        {last}")
        print(f"   Broadcast:        {broadcast}")
    
    print(f"\n🏷️  ประเภท:")
    print(f"   Private:          {'✓' if analysis.is_private else '✗'}")
    print(f"   Loopback:         {'✓' if analysis.is_loopback else '✗'}")
    print(f"   Multicast:        {'✓' if analysis.is_multicast else '✗'}")
    
    if analysis.special_purpose:
        print(f"\n⚠️  วัตถุประสงค์พิเศษ:")
        print(f"   {analysis.special_purpose}")
    
    print("\n" + "=" * 60)


# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    # รายการที่อยู่ IP ทดสอบ
    test_ips = [
        "10.0.0.1",       # Class A Private
        "8.8.8.8",        # Class A Public (Google DNS)
        "172.16.0.100",   # Class B Private
        "150.100.50.25",  # Class B Public
        "192.168.1.1",    # Class C Private
        "203.0.113.50",   # Class C Documentation
        "127.0.0.1",      # Loopback
        "169.254.1.1",    # Link-Local
        "224.0.0.1",      # Multicast
        "240.0.0.1",      # Reserved
    ]
    
    for ip in test_ips:
        print(f"\n{'='*60}")
        analysis = analyze_ipv4(ip)
        print_analysis_report(analysis)

ผลลัพธ์ตัวอย่าง:

============================================================
รายงานการวิเคราะห์ที่อยู่ IPv4: 192.168.1.100
============================================================

📍 ข้อมูลพื้นฐาน:
   ที่อยู่ IP:        192.168.1.100
   Binary:           11000000.10101000.00000001.01100100
   Class:            C

🔢 โครงสร้างที่อยู่:
   Default Mask:     255.255.255.0
   Network ID:       192.168.1
   Host ID:          100
   Network Bits:     24
   Host Bits:        8
   Max Hosts:        254

📊 ช่วงเครือข่าย:
   Network Address:  192.168.1.0
   First Host:       192.168.1.1
   Last Host:        192.168.1.254
   Broadcast:        192.168.1.255

🏷️  ประเภท:
   Private:          ✓
   Loopback:         ✗
   Multicast:        ✗

⚠️  วัตถุประสงค์พิเศษ:
   Private Address (192.168.0.0/16)

============================================================

3.1.3.9 ข้อจำกัดของระบบ Classful และการเปลี่ยนไปใช้ CIDR
graph TB
    subgraph Problems["ปัญหาของ Classful Addressing"]
        P1["⚠️ สิ้นเปลืองที่อยู่
Class A มี 16.7 ล้าน Host
ไม่มีใครต้องการมากขนาดนั้น"] P2["⚠️ ไม่ยืดหยุ่น
ขนาดเครือข่ายคงที่
ปรับแต่งไม่ได้"] P3["⚠️ ที่อยู่หมดเร็ว
Class B หมดก่อน
เพราะเหมาะกับองค์กรส่วนใหญ่"] P4["⚠️ Routing Table ใหญ่
ต้องเก็บ entry มาก
ไม่มี aggregation"] end subgraph Solution["วิธีแก้ไข"] S1["✅ CIDR
(Classless Inter-Domain Routing)
RFC 4632"] S2["✅ VLSM
(Variable Length Subnet Mask)"] S3["✅ NAT
(Network Address Translation)"] S4["✅ IPv6
(128-bit Address)"] end P1 --> S1 P2 --> S2 P3 --> S3 P4 --> S4 style P1 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style P2 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style P3 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style P4 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style S1 fill:#98971a,stroke:#b8bb26,color:#282828 style S2 fill:#98971a,stroke:#b8bb26,color:#282828 style S3 fill:#98971a,stroke:#b8bb26,color:#282828 style S4 fill:#98971a,stroke:#b8bb26,color:#282828

ปัญหาหลักของ Classful Addressing:

ปัญหา คำอธิบาย ผลกระทบ
Address Wastage Class A ให้ 16.7 ล้าน Host แต่องค์กรใหญ่สุดใช้แค่หลักแสน สูญเสียที่อยู่ไปมหาศาล
Inflexibility ขนาดเครือข่ายคงที่ 3 ขนาด ไม่ตรงกับความต้องการจริง
Class B Depletion Class B เหมาะสมที่สุด จึงถูกใช้หมดก่อน ขาดแคลนที่อยู่
Routing Inefficiency ไม่สามารถรวม route ได้ Routing table ใหญ่

ตัวอย่างความสิ้นเปลือง:

องค์กรที่มี 300 เครื่อง:

ประสิทธิภาพการใช้ = 300 65,534 × 100 = 0.46 %

Timeline การเปลี่ยนแปลง:

flowchart LR
    subgraph Era1["1981-1993"]
        A1["Classful
Addressing"] end subgraph Era2["1993"] B1["CIDR
RFC 1518/1519"] end subgraph Era3["1996"] C1["NAT
RFC 1631"] end subgraph Era4["1998-ปัจจุบัน"] D1["IPv6
RFC 2460"] end Era1 -->|"ที่อยู่เริ่มหมด"| Era2 Era2 -->|"ยังไม่พอ"| Era3 Era3 -->|"แก้ปัญหาระยะยาว"| Era4 style A1 fill:#cc241d,stroke:#fb4934,color:#ebdbb2 style B1 fill:#d79921,stroke:#fabd2f,color:#282828 style C1 fill:#98971a,stroke:#b8bb26,color:#282828 style D1 fill:#458588,stroke:#83a598,color:#ebdbb2

3.1.3.10 สรุปการแบ่ง Class ที่อยู่ IPv4

ประเด็นสำคัญที่ต้องจำ:

  1. การระบุ Class: ดูจากบิตแรกๆ ของที่อยู่

  2. Default Subnet Mask:

  3. สูตรคำนวณ:

  4. ที่อยู่พิเศษ:

  5. ปัจจุบัน: ใช้ CIDR แทน Classful เพื่อความยืดหยุ่น

3.1.4 CIDR (Classless Inter-Domain Routing)

CIDR เป็นวิธีการกำหนดที่อยู่ IP ที่ยืดหยุ่นกว่าระบบ Class โดยใช้ prefix length ระบุจำนวนบิตของ network portion

รูปแบบ: IP_Address/prefix_length

ตัวอย่าง: 192.168.1.0/24

สูตรคำนวณจำนวน Host:

จำนวน Host = 2 ( 32 - prefix ) - 2

โดยที่:

CIDR Subnet Mask จำนวน Host ตัวอย่างการใช้งาน
/8 255.0.0.0 16,777,214 ISP ขนาดใหญ่
/16 255.255.0.0 65,534 องค์กรขนาดใหญ่
/24 255.255.255.0 254 สำนักงานขนาดเล็ก
/25 255.255.255.128 126 แผนกงาน
/26 255.255.255.192 62 ห้องประชุม
/27 255.255.255.224 30 Server room
/28 255.255.255.240 14 DMZ
/30 255.255.255.252 2 Point-to-point link
/32 255.255.255.255 1 Host route

3.1.5 ที่อยู่ IPv4 พิเศษ

ประเภท ช่วงที่อยู่ คำอธิบาย
Private Address 10.0.0.0/8 เครือข่ายส่วนตัวขนาดใหญ่
172.16.0.0/12 เครือข่ายส่วนตัวขนาดกลาง
192.168.0.0/16 เครือข่ายส่วนตัวขนาดเล็ก
Loopback 127.0.0.0/8 ทดสอบภายในเครื่อง
Link-Local 169.254.0.0/16 APIPA (ไม่มี DHCP)
Multicast 224.0.0.0/4 ส่งถึงกลุ่มเครื่อง
Broadcast 255.255.255.255 ส่งถึงทุกเครื่องในเครือข่าย

3.2 โปรโตคอล IPv6 (Internet Protocol version 6)

3.2.1 ความหมายและคุณสมบัติของ IPv6

IPv6 (Internet Protocol version 6) คือโปรโตคอลรุ่นใหม่ที่ออกแบบมาเพื่อแทนที่ IPv4 โดยมีคุณสมบัติหลักดังนี้:

3.2.2 โครงสร้างส่วนหัว IPv6 (IPv6 Header Structure)

graph TB
    subgraph IPv6Header["โครงสร้างส่วนหัว IPv6 - 40 ไบต์"]
        direction TB
        V1["Version (4) | Traffic Class (8) | Flow Label (20)"]
        V2["Payload Length (16) | Next Header (8) | Hop Limit (8)"]
        V3["Source Address (128 บิต)"]
        V4["Destination Address (128 บิต)"]
        V1 --> V2 --> V3 --> V4
    end
    
    style V1 fill:#458588,stroke:#83a598,color:#ebdbb2
    style V2 fill:#d79921,stroke:#fabd2f,color:#282828
    style V3 fill:#98971a,stroke:#b8bb26,color:#282828
    style V4 fill:#d65d0e,stroke:#fe8019,color:#ebdbb2
ฟิลด์ ขนาด (บิต) คำอธิบาย
Version 4 เวอร์ชันของ IP (6 สำหรับ IPv6)
Traffic Class 8 เทียบเท่า ToS ใน IPv4
Flow Label 20 ระบุ flow สำหรับ QoS
Payload Length 16 ความยาวของ payload (ไม่รวมส่วนหัว)
Next Header 8 โปรโตคอลชั้นบนหรือ Extension Header
Hop Limit 8 เทียบเท่า TTL ใน IPv4
Source Address 128 ที่อยู่ IPv6 ต้นทาง
Destination Address 128 ที่อยู่ IPv6 ปลายทาง

3.2.3 รูปแบบที่อยู่ IPv6

ที่อยู่ IPv6 แสดงเป็น 8 กลุ่มของเลขฐาน 16 คั่นด้วยเครื่องหมาย colon (:)

รูปแบบเต็ม: 2001:0db8:0000:0000:0000:0000:0000:0001

กฎการย่อ:

  1. ตัด 0 นำหน้าในแต่ละกลุ่มได้: 2001:db8:0:0:0:0:0:1
  2. ใช้ :: แทนกลุ่มที่เป็น 0 ติดกันได้ (ใช้ได้ครั้งเดียว): 2001:db8::1
ประเภทที่อยู่ Prefix ตัวอย่าง คำอธิบาย
Global Unicast 2000::/3 2001:db8::/32 ที่อยู่สาธารณะ
Link-Local fe80::/10 fe80::1 เฉพาะ link เดียว
Unique Local fc00::/7 fd00::/8 เครือข่ายส่วนตัว
Multicast ff00::/8 ff02::1 ส่งถึงกลุ่ม
Loopback ::1/128 ::1 ทดสอบภายในเครื่อง
Unspecified ::/128 :: ยังไม่กำหนดที่อยู่

3.3 โปรโตคอล ICMP (Internet Control Message Protocol)

3.3.1 ความหมายและหน้าที่ของ ICMP

ICMP (Internet Control Message Protocol) คือโปรโตคอลที่ใช้สำหรับส่งข้อความควบคุมและรายงานข้อผิดพลาดในชั้น Network โดย ICMP มีสองเวอร์ชัน:

หน้าที่หลักของ ICMP:

3.3.2 ประเภทข้อความ ICMP ที่สำคัญ

Type ชื่อ คำอธิบาย
0 Echo Reply ตอบกลับ Echo Request (ping)
3 Destination Unreachable ไม่สามารถเข้าถึงปลายทางได้
4 Source Quench ขอให้ลดอัตราการส่ง (deprecated)
5 Redirect แนะนำเส้นทางที่ดีกว่า
8 Echo Request ขอให้ตอบกลับ (ping)
9 Router Advertisement ประกาศตัวเราเตอร์
10 Router Solicitation ขอให้เราเตอร์ประกาศตัว
11 Time Exceeded TTL หมดอายุ (ใช้ใน traceroute)
12 Parameter Problem ปัญหาพารามิเตอร์ในส่วนหัว
sequenceDiagram
    participant H as โฮสต์ (Host)
    participant R1 as เราเตอร์ 1
    participant R2 as เราเตอร์ 2
    participant D as ปลายทาง (Destination)
    
    Note over H,D: กระบวนการ Ping (ICMP Echo)
    
    H->>D: ICMP Echo Request (Type 8)
    D->>H: ICMP Echo Reply (Type 0)
    
    Note over H,D: กระบวนการ Traceroute
    
    H->>R1: IP Packet (TTL=1)
    R1->>H: ICMP Time Exceeded (Type 11)
    Note right of H: บันทึก R1
    
    H->>R2: IP Packet (TTL=2)
    R2->>H: ICMP Time Exceeded (Type 11)
    Note right of H: บันทึก R2
    
    H->>D: IP Packet (TTL=3)
    D->>H: ICMP Echo Reply (Type 0)
    Note right of H: ถึงปลายทาง!

3.3.3 ความเสี่ยงด้านความปลอดภัยของ ICMP

ภัยคุกคาม คำอธิบาย การป้องกัน
ICMP Flood (Ping of Death) ส่ง ICMP จำนวนมากเพื่อทำให้ระบบล่ม จำกัดอัตรา ICMP ที่รับ
Smurf Attack ส่ง ICMP Request ไปยัง broadcast address โดยปลอมที่อยู่ต้นทาง บล็อก broadcast directed
ICMP Redirect Attack ส่ง Redirect ปลอมเพื่อเปลี่ยนเส้นทาง ปิดการรับ ICMP Redirect
Network Scanning ใช้ ICMP ค้นหาโฮสต์ที่ใช้งาน จำกัดการตอบ ICMP

3.4 การเปรียบเทียบ IPv4 และ IPv6

คุณสมบัติ IPv4 IPv6
ขนาดที่อยู่ 32 บิต 128 บิต
รูปแบบที่อยู่ Dotted Decimal (192.168.1.1) Hexadecimal (2001:db8::1)
จำนวนที่อยู่ ~4.3 พันล้าน ~3.4×10³⁸
ขนาดส่วนหัว 20-60 bytes 40 bytes (คงที่)
Checksum มี ไม่มี (ใช้ของชั้นบน)
Fragmentation ทำที่ Router ได้ ทำที่ต้นทางเท่านั้น
Broadcast มี ไม่มี (ใช้ Multicast)
IPsec Optional Mandatory
Auto-configuration DHCP SLAAC + DHCPv6
NAT จำเป็น ไม่จำเป็น

4. การตรวจสอบและวิเคราะห์เครือข่าย

4.1 หลักการวิเคราะห์เครือข่าย

การวิเคราะห์เครือข่าย (Network Analysis) คือกระบวนการตรวจสอบและทำความเข้าใจการทำงานของเครือข่าย โดยมีวัตถุประสงค์หลักดังนี้:

4.2 ระดับของการวิเคราะห์

graph TB
    subgraph Levels["ระดับการวิเคราะห์เครือข่าย"]
        direction TB
        L1["ระดับ 1: การเชื่อมต่อพื้นฐาน
(Connectivity Test)"] L2["ระดับ 2: การวิเคราะห์เส้นทาง
(Path Analysis)"] L3["ระดับ 3: การตรวจสอบบริการ
(Service Verification)"] L4["ระดับ 4: การวิเคราะห์แพ็กเก็ต
(Packet Analysis)"] L5["ระดับ 5: การวิเคราะห์เชิงลึก
(Deep Inspection)"] L1 --> L2 --> L3 --> L4 --> L5 end L1 -.- |"ping, arp"| T1["เครื่องมือ"] L2 -.- |"traceroute, mtr"| T2["เครื่องมือ"] L3 -.- |"ss, nc, curl"| T3["เครื่องมือ"] L4 -.- |"tcpdump, Wireshark"| T4["เครื่องมือ"] L5 -.- |"nmap, IDS/IPS"| T5["เครื่องมือ"] style L1 fill:#98971a,stroke:#b8bb26,color:#282828 style L2 fill:#d79921,stroke:#fabd2f,color:#282828 style L3 fill:#d65d0e,stroke:#fe8019,color:#ebdbb2 style L4 fill:#b16286,stroke:#d3869b,color:#ebdbb2 style L5 fill:#cc241d,stroke:#fb4934,color:#ebdbb2

4.3 เมตริกที่ใช้วัดประสิทธิภาพเครือข่าย

เมตริก คำอธิบาย สูตรคำนวณ/วิธีวัด ค่าที่ดี
Latency เวลาที่ใช้ส่งข้อมูลไป-กลับ RTT จาก ping < 100 ms
Bandwidth ความจุของช่องสัญญาณ iperf, speedtest ตามข้อกำหนด
Throughput ปริมาณข้อมูลที่ส่งได้จริง iperf ใกล้เคียง bandwidth
Packet Loss เปอร์เซ็นต์แพ็กเก็ตที่หาย ping -c 100 < 1%
Jitter ความแปรปรวนของ latency mtr, iperf < 30 ms
Availability เปอร์เซ็นต์เวลาที่ใช้งานได้ monitoring > 99.9%

สูตรคำนวณ Throughput:

Throughput = Bandwidth × ( 1 - Packet Loss Rate )

สูตรคำนวณ Utilization:

Utilization = Throughput Bandwidth × 100 %

5. เครื่องมือวิเคราะห์เครือข่าย

5.1 คำสั่ง ip - การจัดการ Network Interface

5.1.1 ความหมายและการใช้งาน

คำสั่ง ip เป็นเครื่องมือหลักในการจัดการเครือข่ายบน Linux มาแทนที่คำสั่งเก่าอย่าง ifconfig, route, และ arp

"""
สคริปต์สำหรับจัดการ Network Interface ด้วย Python
ใช้ subprocess เรียกคำสั่ง ip
"""

import subprocess
import re
from dataclasses import dataclass
from typing import List, Optional


@dataclass
class NetworkInterface:
    """
    คลาสเก็บข้อมูล Network Interface
    """
    name: str           # ชื่อ interface
    state: str          # สถานะ (UP/DOWN)
    mac_address: str    # ที่อยู่ MAC
    ipv4_address: Optional[str] = None  # ที่อยู่ IPv4
    ipv6_address: Optional[str] = None  # ที่อยู่ IPv6


def run_command(command: List[str]) -> str:
    """
    รันคำสั่งและคืนค่าผลลัพธ์
    
    พารามิเตอร์:
        command: รายการคำสั่งและอาร์กิวเมนต์
        
    คืนค่า:
        ผลลัพธ์จากคำสั่ง
    """
    result = subprocess.run(
        command,
        capture_output=True,
        text=True
    )
    return result.stdout


def get_interfaces() -> List[NetworkInterface]:
    """
    ดึงข้อมูล Network Interface ทั้งหมด
    
    คืนค่า:
        รายการ NetworkInterface
    """
    # รันคำสั่ง ip link show
    output = run_command(['ip', 'link', 'show'])
    
    interfaces = []
    current_interface = None
    
    for line in output.split('\n'):
        # จับชื่อ interface และสถานะ
        match = re.match(r'^\d+:\s+(\S+):.*<(.*)>', line)
        if match:
            name = match.group(1)
            flags = match.group(2)
            state = 'UP' if 'UP' in flags else 'DOWN'
            current_interface = {'name': name, 'state': state}
            
        # จับ MAC address
        mac_match = re.search(r'link/ether\s+([0-9a-f:]+)', line)
        if mac_match and current_interface:
            current_interface['mac'] = mac_match.group(1)
            interfaces.append(current_interface)
            current_interface = None
            
    # ดึงที่อยู่ IP สำหรับแต่ละ interface
    result = []
    for iface in interfaces:
        addr_output = run_command(['ip', 'addr', 'show', iface['name']])
        
        # หา IPv4
        ipv4_match = re.search(r'inet\s+(\d+\.\d+\.\d+\.\d+/\d+)', addr_output)
        # หา IPv6
        ipv6_match = re.search(r'inet6\s+([0-9a-f:]+/\d+)', addr_output)
        
        result.append(NetworkInterface(
            name=iface['name'],
            state=iface['state'],
            mac_address=iface.get('mac', 'N/A'),
            ipv4_address=ipv4_match.group(1) if ipv4_match else None,
            ipv6_address=ipv6_match.group(1) if ipv6_match else None
        ))
        
    return result


def get_routing_table() -> str:
    """
    ดึงตาราง routing
    
    คืนค่า:
        ตาราง routing ในรูปแบบข้อความ
    """
    return run_command(['ip', 'route', 'show'])


def get_arp_table() -> str:
    """
    ดึงตาราง ARP (neighbor)
    
    คืนค่า:
        ตาราง ARP ในรูปแบบข้อความ
    """
    return run_command(['ip', 'neighbor', 'show'])


# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    print("=== Network Interfaces ===")
    for iface in get_interfaces():
        print(f"\nInterface: {iface.name}")
        print(f"  สถานะ: {iface.state}")
        print(f"  MAC: {iface.mac_address}")
        print(f"  IPv4: {iface.ipv4_address or 'ไม่มี'}")
        print(f"  IPv6: {iface.ipv6_address or 'ไม่มี'}")
    
    print("\n=== Routing Table ===")
    print(get_routing_table())
    
    print("\n=== ARP Table ===")
    print(get_arp_table())

5.1.2 ตัวอย่างคำสั่ง ip ที่ใช้บ่อย

คำสั่ง คำอธิบาย
ip link show แสดง interface ทั้งหมด
ip addr show แสดงที่อยู่ IP ทั้งหมด
ip addr add 192.168.1.10/24 dev eth0 เพิ่มที่อยู่ IP
ip addr del 192.168.1.10/24 dev eth0 ลบที่อยู่ IP
ip link set eth0 up เปิด interface
ip link set eth0 down ปิด interface
ip route show แสดงตาราง routing
ip route add default via 192.168.1.1 เพิ่ม default gateway
ip neighbor show แสดงตาราง ARP

5.2 คำสั่ง ping - ทดสอบการเชื่อมต่อ

5.2.1 ความหมายและการทำงาน

คำสั่ง ping ใช้ส่ง ICMP Echo Request ไปยังโฮสต์ปลายทาง และรอรับ ICMP Echo Reply กลับมา เพื่อทดสอบการเชื่อมต่อและวัด latency

"""
สคริปต์ Ping ด้วย Python
ใช้ ICMP socket (ต้องรันด้วยสิทธิ์ root)
"""

import socket
import struct
import time
import os
from typing import Tuple, Optional


def calculate_checksum(data: bytes) -> int:
    """
    คำนวณ ICMP checksum
    
    พารามิเตอร์:
        data: ข้อมูลที่ต้องการคำนวณ checksum
        
    คืนค่า:
        ค่า checksum 16 บิต
    """
    checksum = 0
    count_to = (len(data) // 2) * 2
    
    # รวมทีละ 2 bytes
    for i in range(0, count_to, 2):
        checksum += (data[i] << 8) + data[i + 1]
    
    # ถ้ามี byte เหลือ
    if count_to < len(data):
        checksum += data[-1] << 8
    
    # พับ carry
    checksum = (checksum >> 16) + (checksum & 0xFFFF)
    checksum += checksum >> 16
    
    # One's complement
    return ~checksum & 0xFFFF


def create_icmp_packet(sequence: int, payload_size: int = 56) -> bytes:
    """
    สร้าง ICMP Echo Request packet
    
    พารามิเตอร์:
        sequence: หมายเลขลำดับ
        payload_size: ขนาด payload (default: 56 bytes)
        
    คืนค่า:
        ICMP packet ในรูปแบบ bytes
    """
    icmp_type = 8  # Echo Request
    icmp_code = 0
    icmp_checksum = 0
    icmp_id = os.getpid() & 0xFFFF
    icmp_seq = sequence
    
    # สร้าง payload
    payload = bytes([i & 0xFF for i in range(payload_size)])
    
    # สร้าง header (ยังไม่มี checksum)
    header = struct.pack('!BBHHH', 
                        icmp_type, 
                        icmp_code, 
                        icmp_checksum, 
                        icmp_id, 
                        icmp_seq)
    
    # คำนวณ checksum
    icmp_checksum = calculate_checksum(header + payload)
    
    # สร้าง header ใหม่พร้อม checksum
    header = struct.pack('!BBHHH', 
                        icmp_type, 
                        icmp_code, 
                        icmp_checksum, 
                        icmp_id, 
                        icmp_seq)
    
    return header + payload


def parse_icmp_reply(data: bytes) -> Tuple[int, int, int]:
    """
    แยกวิเคราะห์ ICMP Reply
    
    พารามิเตอร์:
        data: ข้อมูลที่ได้รับ
        
    คืนค่า:
        (type, code, sequence)
    """
    # ข้าม IP header (20 bytes)
    icmp_header = data[20:28]
    icmp_type, icmp_code, _, _, icmp_seq = struct.unpack('!BBHHH', icmp_header)
    return icmp_type, icmp_code, icmp_seq


def ping(host: str, count: int = 4, timeout: float = 2.0) -> dict:
    """
    ส่ง ping ไปยังโฮสต์
    
    พารามิเตอร์:
        host: ที่อยู่ IP หรือ hostname
        count: จำนวนครั้งที่ส่ง
        timeout: เวลารอสูงสุด (วินาที)
        
    คืนค่า:
        ผลลัพธ์การ ping
    """
    try:
        # แปลง hostname เป็น IP
        dest_ip = socket.gethostbyname(host)
    except socket.gaierror:
        return {'error': f'ไม่พบโฮสต์: {host}'}
    
    # สร้าง raw socket สำหรับ ICMP
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
        sock.settimeout(timeout)
    except PermissionError:
        return {'error': 'ต้องรันด้วยสิทธิ์ root'}
    
    results = {
        'host': host,
        'ip': dest_ip,
        'sent': count,
        'received': 0,
        'lost': 0,
        'rtt_list': [],
        'min_rtt': None,
        'max_rtt': None,
        'avg_rtt': None
    }
    
    print(f"PING {host} ({dest_ip}): 56 data bytes")
    
    for seq in range(count):
        # สร้างและส่ง ICMP packet
        packet = create_icmp_packet(seq)
        send_time = time.time()
        
        try:
            sock.sendto(packet, (dest_ip, 0))
            
            # รอรับการตอบกลับ
            data, addr = sock.recvfrom(1024)
            recv_time = time.time()
            
            # วิเคราะห์การตอบกลับ
            icmp_type, icmp_code, reply_seq = parse_icmp_reply(data)
            
            if icmp_type == 0:  # Echo Reply
                rtt = (recv_time - send_time) * 1000  # แปลงเป็น ms
                results['received'] += 1
                results['rtt_list'].append(rtt)
                
                print(f"64 bytes from {addr[0]}: icmp_seq={reply_seq} time={rtt:.3f} ms")
            else:
                print(f"ICMP type={icmp_type} code={icmp_code}")
                
        except socket.timeout:
            print(f"Request timeout for icmp_seq {seq}")
            results['lost'] += 1
            
        # รอก่อนส่งครั้งถัดไป
        time.sleep(1)
    
    sock.close()
    
    # คำนวณสถิติ
    if results['rtt_list']:
        results['min_rtt'] = min(results['rtt_list'])
        results['max_rtt'] = max(results['rtt_list'])
        results['avg_rtt'] = sum(results['rtt_list']) / len(results['rtt_list'])
    
    results['loss_rate'] = (results['lost'] / results['sent']) * 100
    
    return results


# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    import sys
    
    target = sys.argv[1] if len(sys.argv) > 1 else '8.8.8.8'
    
    result = ping(target, count=4)
    
    if 'error' in result:
        print(f"\nข้อผิดพลาด: {result['error']}")
    else:
        print(f"\n--- {result['host']} ping statistics ---")
        print(f"{result['sent']} packets transmitted, "
              f"{result['received']} received, "
              f"{result['loss_rate']:.1f}% packet loss")
        
        if result['avg_rtt']:
            print(f"rtt min/avg/max = "
                  f"{result['min_rtt']:.3f}/"
                  f"{result['avg_rtt']:.3f}/"
                  f"{result['max_rtt']:.3f} ms")

5.2.2 ตัวอย่างคำสั่ง ping

คำสั่ง คำอธิบาย
ping 8.8.8.8 ping ไปยัง Google DNS
ping -c 5 google.com ping 5 ครั้ง
ping -i 0.5 192.168.1.1 ping ทุก 0.5 วินาที
ping -s 1000 host กำหนดขนาด payload 1000 bytes
ping -t 10 host กำหนด TTL เป็น 10
ping -W 1 host timeout 1 วินาที
ping6 ::1 ping IPv6 loopback

5.3 คำสั่ง traceroute - ติดตามเส้นทาง

5.3.1 ความหมายและการทำงาน

คำสั่ง traceroute ใช้ติดตามเส้นทางที่แพ็กเก็ตเดินทางจากต้นทางไปยังปลายทาง โดยอาศัยหลักการของ TTL และ ICMP Time Exceeded

sequenceDiagram
    participant S as ต้นทาง (Source)
    participant R1 as Router 1
    participant R2 as Router 2
    participant R3 as Router 3
    participant D as ปลายทาง (Destination)
    
    Note over S,D: Traceroute Process
    
    S->>R1: Probe 1 (TTL=1)
    R1->>S: ICMP Time Exceeded
    Note right of S: Hop 1: R1 ✓
    
    S->>R1: Probe 2 (TTL=2)
    R1->>R2: Forward (TTL=1)
    R2->>S: ICMP Time Exceeded
    Note right of S: Hop 2: R2 ✓
    
    S->>R1: Probe 3 (TTL=3)
    R1->>R2: Forward (TTL=2)
    R2->>R3: Forward (TTL=1)
    R3->>S: ICMP Time Exceeded
    Note right of S: Hop 3: R3 ✓
    
    S->>R1: Probe 4 (TTL=4)
    R1->>R2: Forward (TTL=3)
    R2->>R3: Forward (TTL=2)
    R3->>D: Forward (TTL=1)
    D->>S: ICMP Port Unreachable / Echo Reply
    Note right of S: ถึงปลายทาง!

5.3.2 ตัวอย่างคำสั่ง traceroute

คำสั่ง คำอธิบาย
traceroute google.com traceroute ปกติ (UDP)
traceroute -I google.com ใช้ ICMP แทน UDP
traceroute -T google.com ใช้ TCP SYN
traceroute -m 20 host กำหนด max hops เป็น 20
traceroute -q 5 host ส่ง 5 probes ต่อ hop
traceroute -n host ไม่ resolve DNS
traceroute6 ipv6.google.com traceroute IPv6

5.4 คำสั่ง ss - ดูการเชื่อมต่อเครือข่าย

5.4.1 ความหมายและการใช้งาน

คำสั่ง ss (Socket Statistics) ใช้แสดงข้อมูลเกี่ยวกับ socket และการเชื่อมต่อเครือข่าย มาแทนที่คำสั่ง netstat

"""
สคริปต์วิเคราะห์การเชื่อมต่อเครือข่ายด้วย Python
แยกวิเคราะห์ผลลัพธ์จากคำสั่ง ss
"""

import subprocess
import re
from dataclasses import dataclass
from typing import List, Dict
from collections import Counter


@dataclass
class SocketConnection:
    """
    คลาสเก็บข้อมูลการเชื่อมต่อ Socket
    """
    protocol: str       # TCP, UDP
    state: str          # LISTEN, ESTABLISHED, etc.
    recv_q: int         # Receive queue
    send_q: int         # Send queue
    local_address: str  # ที่อยู่และพอร์ตภายใน
    peer_address: str   # ที่อยู่และพอร์ตของ peer
    process: str = ""   # ชื่อ process (ถ้ามี)


def get_socket_stats() -> List[SocketConnection]:
    """
    ดึงข้อมูล socket ทั้งหมด
    
    คืนค่า:
        รายการ SocketConnection
    """
    # รันคำสั่ง ss -tunap
    # t = TCP, u = UDP, n = numeric, a = all, p = process
    result = subprocess.run(
        ['ss', '-tunap'],
        capture_output=True,
        text=True
    )
    
    connections = []
    lines = result.stdout.strip().split('\n')[1:]  # ข้าม header
    
    for line in lines:
        parts = line.split()
        if len(parts) >= 5:
            conn = SocketConnection(
                protocol=parts[0],
                state=parts[1],
                recv_q=int(parts[2]),
                send_q=int(parts[3]),
                local_address=parts[4],
                peer_address=parts[5] if len(parts) > 5 else '*:*',
                process=parts[-1] if 'users:' in line else ''
            )
            connections.append(conn)
    
    return connections


def analyze_connections(connections: List[SocketConnection]) -> Dict:
    """
    วิเคราะห์การเชื่อมต่อ
    
    พารามิเตอร์:
        connections: รายการการเชื่อมต่อ
        
    คืนค่า:
        ผลการวิเคราะห์
    """
    analysis = {
        'total': len(connections),
        'by_protocol': Counter(),
        'by_state': Counter(),
        'listening_ports': [],
        'established': [],
        'high_recv_q': [],  # connections ที่มี recv queue สูง
    }
    
    for conn in connections:
        analysis['by_protocol'][conn.protocol] += 1
        analysis['by_state'][conn.state] += 1
        
        if conn.state == 'LISTEN':
            # ดึงพอร์ตที่ listening
            port = conn.local_address.split(':')[-1]
            analysis['listening_ports'].append({
                'port': port,
                'address': conn.local_address,
                'process': conn.process
            })
            
        elif conn.state == 'ESTAB':
            analysis['established'].append({
                'local': conn.local_address,
                'peer': conn.peer_address,
                'process': conn.process
            })
            
        # ตรวจสอบ recv queue ที่สูง
        if conn.recv_q > 1000:
            analysis['high_recv_q'].append({
                'connection': f"{conn.local_address} -> {conn.peer_address}",
                'recv_q': conn.recv_q
            })
    
    return analysis


def print_report(analysis: Dict):
    """
    พิมพ์รายงานการวิเคราะห์
    
    พารามิเตอร์:
        analysis: ผลการวิเคราะห์
    """
    print("=" * 50)
    print("รายงานการวิเคราะห์การเชื่อมต่อเครือข่าย")
    print("=" * 50)
    
    print(f"\nจำนวนการเชื่อมต่อทั้งหมด: {analysis['total']}")
    
    print("\n--- แยกตามโปรโตคอล ---")
    for proto, count in analysis['by_protocol'].items():
        print(f"  {proto}: {count}")
    
    print("\n--- แยกตามสถานะ ---")
    for state, count in analysis['by_state'].items():
        print(f"  {state}: {count}")
    
    print(f"\n--- พอร์ตที่ Listening ({len(analysis['listening_ports'])}) ---")
    for port_info in analysis['listening_ports'][:10]:
        print(f"  {port_info['address']} {port_info['process']}")
    
    if analysis['high_recv_q']:
        print(f"\n--- การเชื่อมต่อที่มี Recv Queue สูง ---")
        for conn in analysis['high_recv_q']:
            print(f"  {conn['connection']}: {conn['recv_q']} bytes")


# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    connections = get_socket_stats()
    analysis = analyze_connections(connections)
    print_report(analysis)

5.4.2 ตัวอย่างคำสั่ง ss

คำสั่ง คำอธิบาย
ss -t แสดง TCP connections
ss -u แสดง UDP connections
ss -l แสดงเฉพาะ listening sockets
ss -a แสดงทั้งหมด (listening + non-listening)
ss -n แสดงหมายเลขพอร์ต (ไม่ resolve)
ss -p แสดง process ที่ใช้ socket
ss -s แสดงสรุปสถิติ
ss -t state established แสดงเฉพาะ ESTABLISHED
ss 'sport = :22' กรองเฉพาะ source port 22
ss 'dport = :443' กรองเฉพาะ destination port 443

5.5 คำสั่ง arp - จัดการ ARP Table

5.5.1 ความหมายและการทำงาน

ARP (Address Resolution Protocol) ใช้แปลงที่อยู่ IP เป็นที่อยู่ MAC สำหรับการส่งข้อมูลในเครือข่ายท้องถิ่น (LAN)

sequenceDiagram
    participant A as Host A
192.168.1.10
MAC: AA:AA:AA:AA:AA:AA participant B as Host B
192.168.1.20
MAC: BB:BB:BB:BB:BB:BB participant BC as Broadcast Note over A,B: ARP Request/Reply Process A->>BC: ARP Request (Broadcast)
Who has 192.168.1.20?
Tell 192.168.1.10 Note over A: ส่ง broadcast
ไปทุกเครื่องในเครือข่าย B->>A: ARP Reply (Unicast)
192.168.1.20 is at
BB:BB:BB:BB:BB:BB Note over A: บันทึกลง
ARP Cache Note over A,B: ตอนนี้ Host A รู้ MAC ของ Host B แล้ว A->>B: Data Frame
Src MAC: AA:AA...
Dst MAC: BB:BB...

5.5.2 ตัวอย่างคำสั่ง ARP

คำสั่ง คำอธิบาย
arp -a แสดง ARP table ทั้งหมด
arp -n แสดง ARP table (ไม่ resolve)
ip neighbor show แสดง neighbor table (แทน arp)
ip neighbor add 192.168.1.100 lladdr AA:BB:CC:DD:EE:FF dev eth0 เพิ่ม static entry
ip neighbor del 192.168.1.100 dev eth0 ลบ entry
ip neighbor flush dev eth0 ล้าง ARP cache

5.6 Wireshark - วิเคราะห์แพ็กเก็ต

5.6.1 ความหมายและความสามารถ

Wireshark คือเครื่องมือวิเคราะห์แพ็กเก็ตแบบกราฟิก (GUI) ที่ทรงพลังที่สุด สามารถ:

5.6.2 Display Filters ที่ใช้บ่อย

Filter คำอธิบาย
ip.addr == 192.168.1.1 แพ็กเก็ตที่มี IP นี้
ip.src == 10.0.0.1 แพ็กเก็ตจาก IP นี้
ip.dst == 8.8.8.8 แพ็กเก็ตไปยัง IP นี้
tcp เฉพาะ TCP
udp เฉพาะ UDP
icmp เฉพาะ ICMP
tcp.port == 80 TCP port 80
tcp.flags.syn == 1 TCP SYN packets
http HTTP traffic
dns DNS traffic
tcp.analysis.retransmission TCP retransmissions
frame.time >= "2024-01-01" หลังวันที่กำหนด

5.6.3 การใช้ tcpdump (Command Line Alternative)

"""
สคริปต์วิเคราะห์แพ็กเก็ตด้วย scapy
ต้องติดตั้ง: pip install scapy
"""

try:
    from scapy.all import sniff, IP, TCP, UDP, ICMP, ARP
    from scapy.layers.http import HTTPRequest
    SCAPY_AVAILABLE = True
except ImportError:
    SCAPY_AVAILABLE = False

from datetime import datetime
from collections import Counter
from typing import Dict, List
import time


class PacketAnalyzer:
    """
    คลาสสำหรับวิเคราะห์แพ็กเก็ต
    """
    
    def __init__(self):
        """
        กำหนดค่าเริ่มต้น
        """
        self.packets = []
        self.stats = {
            'total': 0,
            'protocols': Counter(),
            'src_ips': Counter(),
            'dst_ips': Counter(),
            'ports': Counter(),
            'packet_sizes': []
        }
        
    def packet_callback(self, packet):
        """
        Callback function สำหรับทุกแพ็กเก็ตที่จับได้
        
        พารามิเตอร์:
            packet: แพ็กเก็ตที่จับได้
        """
        self.stats['total'] += 1
        self.packets.append(packet)
        
        # วิเคราะห์ IP layer
        if IP in packet:
            ip_layer = packet[IP]
            self.stats['src_ips'][ip_layer.src] += 1
            self.stats['dst_ips'][ip_layer.dst] += 1
            self.stats['packet_sizes'].append(len(packet))
            
            # ระบุโปรโตคอล
            if TCP in packet:
                self.stats['protocols']['TCP'] += 1
                tcp_layer = packet[TCP]
                self.stats['ports'][tcp_layer.dport] += 1
                self._print_tcp_info(packet)
                
            elif UDP in packet:
                self.stats['protocols']['UDP'] += 1
                udp_layer = packet[UDP]
                self.stats['ports'][udp_layer.dport] += 1
                self._print_udp_info(packet)
                
            elif ICMP in packet:
                self.stats['protocols']['ICMP'] += 1
                self._print_icmp_info(packet)
                
        elif ARP in packet:
            self.stats['protocols']['ARP'] += 1
            self._print_arp_info(packet)
            
    def _print_tcp_info(self, packet):
        """แสดงข้อมูล TCP packet"""
        ip = packet[IP]
        tcp = packet[TCP]
        flags = tcp.sprintf('%TCP.flags%')
        print(f"[TCP] {ip.src}:{tcp.sport} -> {ip.dst}:{tcp.dport} "
              f"[{flags}] Len={len(packet)}")
        
    def _print_udp_info(self, packet):
        """แสดงข้อมูล UDP packet"""
        ip = packet[IP]
        udp = packet[UDP]
        print(f"[UDP] {ip.src}:{udp.sport} -> {ip.dst}:{udp.dport} "
              f"Len={len(packet)}")
        
    def _print_icmp_info(self, packet):
        """แสดงข้อมูล ICMP packet"""
        ip = packet[IP]
        icmp = packet[ICMP]
        print(f"[ICMP] {ip.src} -> {ip.dst} "
              f"Type={icmp.type} Code={icmp.code}")
        
    def _print_arp_info(self, packet):
        """แสดงข้อมูล ARP packet"""
        arp = packet[ARP]
        op = "Request" if arp.op == 1 else "Reply"
        print(f"[ARP {op}] {arp.psrc} ({arp.hwsrc}) -> "
              f"{arp.pdst} ({arp.hwdst})")
        
    def start_capture(self, interface: str = None, count: int = 100, 
                      filter_str: str = None):
        """
        เริ่มจับแพ็กเก็ต
        
        พารามิเตอร์:
            interface: ชื่อ interface (None = ทั้งหมด)
            count: จำนวนแพ็กเก็ตที่จะจับ
            filter_str: BPF filter string
        """
        if not SCAPY_AVAILABLE:
            print("ต้องติดตั้ง scapy: pip install scapy")
            return
            
        print(f"เริ่มจับแพ็กเก็ต (จำนวน: {count})...")
        print("=" * 60)
        
        sniff(
            iface=interface,
            count=count,
            filter=filter_str,
            prn=self.packet_callback,
            store=False
        )
        
    def print_summary(self):
        """
        พิมพ์สรุปการวิเคราะห์
        """
        print("\n" + "=" * 60)
        print("สรุปการวิเคราะห์แพ็กเก็ต")
        print("=" * 60)
        
        print(f"\nจำนวนแพ็กเก็ตทั้งหมด: {self.stats['total']}")
        
        print("\n--- โปรโตคอล ---")
        for proto, count in self.stats['protocols'].most_common():
            print(f"  {proto}: {count}")
            
        print("\n--- Top 5 Source IPs ---")
        for ip, count in self.stats['src_ips'].most_common(5):
            print(f"  {ip}: {count}")
            
        print("\n--- Top 5 Destination IPs ---")
        for ip, count in self.stats['dst_ips'].most_common(5):
            print(f"  {ip}: {count}")
            
        print("\n--- Top 5 Destination Ports ---")
        for port, count in self.stats['ports'].most_common(5):
            service = self._get_service_name(port)
            print(f"  {port} ({service}): {count}")
            
        if self.stats['packet_sizes']:
            avg_size = sum(self.stats['packet_sizes']) / len(self.stats['packet_sizes'])
            print(f"\n--- ขนาดแพ็กเก็ต ---")
            print(f"  เฉลี่ย: {avg_size:.1f} bytes")
            print(f"  ต่ำสุด: {min(self.stats['packet_sizes'])} bytes")
            print(f"  สูงสุด: {max(self.stats['packet_sizes'])} bytes")
            
    def _get_service_name(self, port: int) -> str:
        """แปลงหมายเลขพอร์ตเป็นชื่อบริการ"""
        services = {
            20: 'FTP-DATA', 21: 'FTP', 22: 'SSH', 23: 'TELNET',
            25: 'SMTP', 53: 'DNS', 67: 'DHCP', 68: 'DHCP',
            80: 'HTTP', 110: 'POP3', 143: 'IMAP', 443: 'HTTPS',
            3306: 'MySQL', 5432: 'PostgreSQL', 6379: 'Redis'
        }
        return services.get(port, 'Unknown')


# ตัวอย่างการใช้งาน
if __name__ == "__main__":
    analyzer = PacketAnalyzer()
    
    # จับ 50 แพ็กเก็ต กรองเฉพาะ TCP
    # ต้องรันด้วยสิทธิ์ root
    try:
        analyzer.start_capture(count=50, filter_str="tcp")
        analyzer.print_summary()
    except PermissionError:
        print("ต้องรันด้วยสิทธิ์ root: sudo python script.py")

5.6.4 ตัวอย่างคำสั่ง tcpdump

คำสั่ง คำอธิบาย
tcpdump -i eth0 จับแพ็กเก็ตบน eth0
tcpdump -c 100 จับ 100 แพ็กเก็ต
tcpdump -w capture.pcap บันทึกลงไฟล์
tcpdump -r capture.pcap อ่านจากไฟล์
tcpdump host 192.168.1.1 กรองตาม host
tcpdump port 80 กรองตาม port
tcpdump tcp เฉพาะ TCP
tcpdump 'tcp[tcpflags] & tcp-syn != 0' เฉพาะ SYN packets
tcpdump -n -v ไม่ resolve DNS, verbose

6. สรุปโดยรวม

6.1 สรุปเนื้อหา

เอกสารนี้ครอบคลุมหัวข้อสำคัญของ โปรโตคอลเครือข่ายและการวิเคราะห์ ดังนี้:

โปรโตคอลชั้นขนส่ง (Transport Layer)

โปรโตคอลชั้นเครือข่าย (Network Layer)

เครื่องมือวิเคราะห์เครือข่าย

เครื่องมือ หน้าที่หลัก ระดับการวิเคราะห์
ip จัดการ interface, routing, ARP พื้นฐาน
ping ทดสอบการเชื่อมต่อ การเชื่อมต่อ
traceroute ติดตามเส้นทาง เส้นทาง
ss ตรวจสอบ socket และการเชื่อมต่อ บริการ
arp จัดการ ARP table การแปลงที่อยู่
Wireshark/tcpdump วิเคราะห์แพ็กเก็ตเชิงลึก แพ็กเก็ต

6.2 แผนภาพสรุปความสัมพันธ์

graph TB
    subgraph Application["ชั้น Application"]
        HTTP["HTTP/HTTPS"]
        FTP["FTP/SFTP"]
        DNS["DNS"]
        VOIP["VoIP"]
    end
    
    subgraph Transport["ชั้น Transport"]
        TCP["TCP
Connection-oriented
Reliable"] UDP["UDP
Connectionless
Fast"] end subgraph Network["ชั้น Network"] IPv4["IPv4
32-bit address"] IPv6["IPv6
128-bit address"] ICMP["ICMP
Control messages"] end subgraph Tools["เครื่องมือวิเคราะห์"] PING["ping"] TRACE["traceroute"] SS["ss"] WIRE["Wireshark"] end HTTP --> TCP FTP --> TCP DNS --> UDP VOIP --> UDP TCP --> IPv4 TCP --> IPv6 UDP --> IPv4 UDP --> IPv6 ICMP --> IPv4 ICMP --> IPv6 PING -.-> ICMP TRACE -.-> ICMP SS -.-> TCP SS -.-> UDP WIRE -.-> TCP WIRE -.-> UDP WIRE -.-> ICMP style TCP fill:#458588,stroke:#83a598,color:#ebdbb2 style UDP fill:#98971a,stroke:#b8bb26,color:#282828 style IPv4 fill:#d79921,stroke:#fabd2f,color:#282828 style IPv6 fill:#d65d0e,stroke:#fe8019,color:#ebdbb2 style ICMP fill:#b16286,stroke:#d3869b,color:#ebdbb2

6.3 ข้อควรจำ

  1. TCP vs UDP: เลือกใช้ตามความต้องการของแอปพลิเคชัน - TCP สำหรับความน่าเชื่อถือ, UDP สำหรับความเร็ว

  2. IPv4 vs IPv6: IPv6 คืออนาคต แต่ปัจจุบันยังต้องใช้ Dual Stack

  3. การวิเคราะห์เครือข่าย: เริ่มจากเครื่องมือง่ายๆ (ping) ก่อนใช้เครื่องมือซับซ้อน (Wireshark)

  4. ความปลอดภัย: ICMP และ ARP เป็นช่องทางโจมตีที่พบบ่อย ควรจำกัดการใช้งาน

  5. การเฝ้าระวัง: ตรวจสอบ Recv Queue, Packet Loss, และ Latency อย่างสม่ำเสมอ


7. เอกสารอ้างอิง

7.1 มาตรฐาน RFC

RFC ชื่อ คำอธิบาย
RFC 791 Internet Protocol IPv4 Specification
RFC 792 Internet Control Message Protocol ICMP for IPv4
RFC 793 Transmission Control Protocol TCP Specification
RFC 768 User Datagram Protocol UDP Specification
RFC 8200 Internet Protocol, Version 6 IPv6 Specification
RFC 4443 ICMPv6 ICMP for IPv6
RFC 5681 TCP Congestion Control TCP CC Algorithms
RFC 6335 Port Numbers IANA Port Assignments

7.2 หนังสือแนะนำ

  1. Computer Networking: A Top-Down Approach - James F. Kurose, Keith W. Ross

  2. TCP/IP Illustrated, Volume 1 - W. Richard Stevens

  3. Wireshark Network Analysis - Laura Chappell

  4. Network Security Essentials - William Stallings

7.3 แหล่งข้อมูลออนไลน์

7.4 เครื่องมือที่แนะนำ

เครื่องมือ ลิงก์ ใบอนุญาต
Wireshark https://www.wireshark.org/ GPL
Nmap https://nmap.org/ GPL
iPerf3 https://iperf.fr/ BSD
mtr https://github.com/traviscross/mtr GPL
Scapy https://scapy.net/ GPL