OSI Layer 4 of 7

Transport Layer

เปลี่ยนบริการส่ง packet ระหว่าง host ให้กลายเป็นช่องทางสื่อสารระหว่าง process ด้วย port, UDP, TCP และกลไกที่ application เรียกผ่าน Socket API

🔗
เทียบเท่าใน TCP/IP: Transport Layer (ชื่อเดียวกัน เนื้อหาเดียวกัน) — อ่านฉบับกระชับ →

1คุณสมบัติที่คาดหวังจาก Transport Protocol

Transport Layer ไม่ได้มีหน้าที่ทำให้ทุกการสื่อสารเชื่อถือได้เหมือนกัน แต่เปิดบริการหลายแบบให้ application เลือก TCP เพิ่ม byte stream ที่มีลำดับและการส่งซ้ำ ส่วน UDP รักษาขอบเขต datagram และเพิ่ม port กับ checksum โดยไม่สร้าง connection หรือ retransmission ให้ การออกแบบจึงเริ่มจากถามว่า application ต้องการคุณสมบัติใด ไม่ใช่เริ่มจากตัดสินว่า protocol หนึ่ง “ดีกว่า” อีก protocol หนึ่ง

คุณสมบัติที่ Transport Protocol อาจจัดให้
  • รับประกันการส่งถึง
  • ส่งถึงตามลำดับ
  • ส่งซ้ำไม่เกิน 1 ชุด
  • รองรับ message ขนาดใหญ่
  • รองรับ synchronization
  • ให้ receiver ทำ flow control
  • รองรับหลาย process ต่อโฮสต์
ข้อจำกัดของเครือข่ายที่ต้องรับมือ
  • Drop message
  • Reorder message
  • Duplicate message
  • จำกัดขนาด message
  • Delay ไม่แน่นอน
IP พาไปถึงอาคาร ส่วน Transport พาไปถึงแผนก

IP address ช่วยพา packet ไปยังเครื่องหนึ่ง แต่เครื่องเดียวอาจมีเว็บเซิร์ฟเวอร์ DNS โปรแกรมประชุม และฐานข้อมูลทำงานพร้อมกัน Port number คล้ายหมายเลขแผนกที่บอกว่าซองนี้ควรถูกส่งให้ process ใด

TCP กับ UDP เปรียบเหมือนบริการรับส่งสองแบบ UDP รับซองแต่ละใบแยกจากกัน ไม่โทรตามเมื่อหาย ส่วน TCP สร้างรายการลำดับและติดตามว่าส่วนใดถึงแล้ว แต่ TCP มองข้อมูลเป็นสาย byte ต่อเนื่อง จึงไม่ได้รักษารอยแบ่งซองเดิมของ application ไว้ให้

Multiplexing และ Demultiplexing

ฝั่งส่งมีหลาย process เขียนข้อมูลลง socket Transport Layer จึง multiplex ข้อมูลเหล่านั้นลงสู่ Network Layer พร้อมข้อมูลกำกับ ฝั่งรับอ่าน destination port และบริบทของ connection เพื่อ demultiplex ไปยัง socket ที่ถูกต้อง UDP socket มักจับคู่ด้วย local address/port ส่วน TCP connection แยกด้วย tuple ที่รวม source address, source port, destination address และ destination port ทำให้ server port เดียวรับ client หลายรายพร้อมกันได้

คำความหมายอย่าสับสนกับ
Portหมายเลขใน transport header ใช้ช่วยเลือก endpoint/processไม่ใช่ physical switch port และไม่ใช่ process ID
Socketทรัพยากร/endpoint ที่ process ใช้เรียกบริการสื่อสารของ OSไม่ใช่ connection เสมอไป UDP socket ใช้ได้โดยไม่ connect
Connectionstate ร่วมที่ endpoint ใช้ตีความลำดับ window และ lifecycleไม่ได้หมายถึงมีสายกายภาพจองตลอดทาง
Port บอกบริการ แต่ไม่ได้พิสูจน์ตัวตน
การเห็น traffic ไป port 443 บอกได้ว่าโดยธรรมเนียมมักใช้ HTTPS แต่ application สามารถใช้ port อื่นหรือวาง protocol อื่นบน 443 ได้ การระบุ port จึงช่วย demultiplex ไม่ใช่หลักฐานว่า payload ปลอดภัยหรือ server เป็นใคร

2Simple Demultiplexer (UDP)

บทบาทของ UDP
ขยาย host-to-host delivery ให้เป็น process-to-process datagram service ผ่าน port number และมี checksum ตรวจความเสียหาย UDP ไม่ทำ retransmission, ordering, flow control หรือ congestion control ให้โดยตัว protocol หาก application ต้องการต้องออกแบบเพิ่มหรือใช้ protocol อื่นบน UDP
Fieldความหมาย
SrcPort / DstPortใช้ demux ไปยัง process ที่ถูกต้อง
Length / Checksumความยาว UDP datagram / ตรวจความเสียหายด้วย pseudo-header และข้อมูล Checksum เป็น optional ใน IPv4 แบบดั้งเดิม แต่ใช้บังคับใน IPv6 โดยทั่วไป ยกเว้นกรณีเฉพาะที่มาตรฐานกำหนด

UDP รักษาขอบเขต message: การส่ง datagram สองครั้งทำให้ฝั่งรับเห็น datagram แยกกันหากทั้งสองมาถึง ต่างจาก TCP ที่รวมเป็น byte stream แต่ datagram อาจหาย มาไม่เรียง หรือซ้ำได้ และถ้าใหญ่เกิน path MTU อาจถูก fragment หรือส่งไม่ผ่านตาม IP version และ policy

ระบบปฏิบัติการมี receive buffer ให้ socket หาก application อ่านไม่ทัน buffer อาจเต็มและ kernel ทิ้ง datagram พฤติกรรมการรายงานขึ้นกับ OS และ API ผู้ส่งมักไม่รู้ว่าฝั่งรับทิ้งจาก buffer เต็ม การเรียก sendto() สำเร็จจึงบอกเพียงว่าระบบรับข้อมูลไปจัดการ ไม่ได้ยืนยันว่า process ปลายทางอ่านแล้ว

UDP เหมือนโยนโปสการ์ดลงตู้ไปรษณีย์
แต่ละใบมีขอบเขตชัดและอ่านแยกกัน ไม่ต้องโทรนัดก่อนส่ง แต่ผู้ส่งไม่ได้รับใบตอบรับอัตโนมัติ ถ้าต้องการรู้ว่าถึงหรือไม่ ต้องเขียนหมายเลขรายการ ให้ผู้รับตอบกลับ ตั้ง timeout และคิดเรื่องของซ้ำเอง เมื่อเพิ่มครบมากพอ เรากำลังสร้าง transport protocol ของ application ขึ้นมาบน UDP

เมื่อใด UDP เหมาะกว่า

UDP เบา แต่ Application ไม่ได้เบาตามเสมอ
Header UDP เล็กและไม่มี connection state ใน protocol แต่ถ้า application ต้องเพิ่ม ACK, retry, ordering, encryption และ congestion control เอง ความซับซ้อนย้ายตำแหน่ง ไม่ได้หายไป การเลือก UDP เพราะ “เร็วกว่าเสมอ” จึงเป็นเหตุผลที่ยังไม่ครบ

3Reliable Byte Stream (TCP)

TCP ให้บริการ: Reliable, Connection-oriented, Byte-stream service

Reliable ในที่นี้หมายถึง TCP พยายามส่ง byte ที่ application เขียนให้ถึงอีกฝั่งตามลำดับและไม่ส่ง duplicate byte ให้ application ภายใต้ connection ที่ยังทำงาน แต่ไม่ได้รับประกัน deadline และไม่สามารถกู้ข้อมูลได้ถ้า connection ขาดจน retry ไม่สำเร็จ Application ยังต้องรับมือ error, timeout และกรณีที่ไม่รู้ว่าฝั่งตรงข้ามทำงานระดับ application เสร็จหรือยัง

TCP เป็นท่อน้ำ ไม่ใช่สายพานกล่อง

ถ้า application ส่งข้อความ A แล้วส่งข้อความ B ต่อ TCP เห็นเพียง byte ของ A ต่อด้วย byte ของ B ฝั่งรับอาจอ่านได้ครึ่ง A, A+B พร้อมกัน หรือส่วนท้าย A กับต้น B ในครั้งเดียว ขึ้นกับ buffer และ timing ขอบเขตของการเรียก send() ไม่ถูกส่งไปเป็นขอบเขตของ recv()

Application จึงต้องสร้าง message framing เอง เช่นใส่ length prefix, delimiter หรือใช้ protocol ที่ระบุรูปแบบชัด การมี TCP ไม่ได้ทำให้ JSON สองก้อนแยกตัวออกจากกันด้วยความสุภาพ

Sequence Number นับ Byte ไม่ได้นับ Segment

TCP segment ที่มี Sequence Number 1,000 และ payload 500 byte ครอบคลุม byte 1,000–1,499 ACK 1,500 โดยทั่วไปหมายถึงได้รับ byte ก่อนหน้า 1,500 ครบและกำลังรอ byte 1,500 ACK เป็น cumulative จึงยืนยันช่วงต่อเนื่อง ไม่ได้หมายถึง “ได้รับ segment หมายเลข 1,500”

Segment boundary เปลี่ยนได้ระหว่าง retransmission ผู้ส่งอาจส่ง byte เดิมด้วยขนาด segment ต่างจากรอบแรก Receiver จัดข้อมูลด้วย sequence space ของ byte จึงประกอบ stream ได้โดยไม่ต้องรักษารูปร่าง segment เดิม SYN และ FIN ใช้พื้นที่หนึ่งตำแหน่งใน sequence space แม้ไม่บรรทุก application byte ซึ่งอธิบายว่าทำไม handshake ACK เป็น x+1

Flow ControlCongestion Control
ป้องกันอะไรsender ส่งเร็วเกินความสามารถของ receiverข้อมูลถูกยัดเข้าเครือข่ายจนเกิด overload
Feedback"Receiver overflowing""Not much getting through"

Flow control ปกป้อง receive buffer ของ endpoint ผ่าน advertised receive window หรือ rwnd ส่วน congestion control จำกัดข้อมูลตามสภาพเครือข่ายผ่าน congestion window หรือ cwnd ผู้ส่งส่งข้อมูลที่ยังไม่ ACK ได้โดยประมาณไม่เกิน min(rwnd, cwnd) และยังถูกจำกัดด้วยข้อมูลที่ application มี, sender buffer และ implementation อื่นด้วย

สองหน้าต่าง สองคนที่ต้องไม่ถูกท่วม
Flow control เหมือนโกดังปลายทางบอกว่ายังมีที่ว่างกี่กล่อง Congestion control เหมือนถนนบอกผ่านอาการรถหายหรือ ECN ว่ากำลังแน่น ต่อให้โกดังว่างมาก รถก็ไม่ควรทะลักเข้าถนน และต่อให้ถนนโล่ง ถ้าโกดังเต็มผู้ส่งก็ต้องหยุด
Field ใน TCP Headerความหมาย
SequenceNumsequence number ของ byte แรกในข้อมูลที่ segment นี้บรรทุก (TCP เป็น byte-oriented)
Acknowledgment / AdvertisedWindowข้อมูลการไหลของข้อมูลทิศตรงข้าม ใช้ทำ sliding window
FlagsSYN/FIN เริ่ม/ปิด connection, ACK Acknowledgment ใช้งานได้, URG ข้อมูลด่วน, PUSH แจ้ง receiving process ทันที, RESET ยกเลิก connection

TCP checksum ตรวจ segment ร่วมกับ pseudo-header ที่รวม address และ protocol เพื่อช่วยจับการส่งผิดปลายทาง Header ยังมี Data Offset, window, checksum, urgent pointer และ options เช่น MSS, Window Scale, SACK Permitted และ Timestamps ขนาด header จึงไม่คงที่ 20 byte เสมอ

PSH และ URG มักถูกอธิบายกว้างเกินจริง PSH ไม่ได้สร้าง message boundary หรือรับประกันว่า application จะถูกปลุก “ทันที” แบบ deadline ส่วน urgent mechanism มี semantics ที่ใช้งานและตีความต่างกันในประวัติศาสตร์และไม่ใช่กลไก priority ทั่วไป Application สมัยใหม่ควรพึ่ง protocol framing และ API semantics ที่ชัดกว่า

3-Way Handshake
1) Client→Server: SYN, Seq=x
2) Server→Client: SYN+ACK, Seq=y, Ack=x+1
3) Client→Server: ACK, Ack=y+1

Handshake ทำสามเรื่องพร้อมกัน: ยืนยันว่าเส้นทางสื่อสารสองทิศพอใช้งาน แลก initial sequence numbers และเจรจา options บางส่วน SYN flood ใช้ประโยชน์จากช่วงที่ server เก็บ half-open state โดยส่ง SYN จำนวนมากแต่ไม่จบ handshake กลไก SYN cookies หรือ backlog management ลดผลกระทบ แต่มีข้อแลกเปลี่ยนและรายละเอียดตาม implementation

TCP Connected ไม่ได้แปลว่า Application พร้อม
connect() สำเร็จบอกว่า TCP handshake สำเร็จ ไม่ได้ยืนยันว่า user authenticated, database พร้อม หรือ request จะสำเร็จ Server อาจ accept connection แล้วปิดทันที หรือ application protocol อาจตอบ error การแยก transport success จาก application success เป็นทักษะสำคัญในการ debug
การปิด Connection (4 ขั้นตอน)
แต่ละทิศของ TCP ปิดแยกกันได้ ฝั่งหนึ่งส่ง FIN อีกฝั่ง ACK แล้วอาจยังส่งข้อมูลกลับต่อ เมื่อพร้อมจึงส่ง FIN ของตน ฝั่งที่เป็น active closer ตอบ ACK และเข้าสถานะ TIME_WAIT โดยทั่วไป ลำดับจริงอาจรวม ACK+FIN หรือแตกต่างตามผู้ที่เริ่มปิด จึงไม่ควรผูกคำว่า client/server ตายตัวกับ active close

TIME_WAIT ช่วยให้ ACK สุดท้ายถูกส่งซ้ำได้หาก FIN กลับมา และให้ segment เก่าหมดอายุก่อน tuple เดิมถูกนำกลับมาใช้ ระยะเวลาขึ้นกับ implementation และการกำหนด MSL ไม่ควรจำว่า MSL บน Internet เท่ากับ 120 วินาทีเป็นกฎสากลทุกระบบ นอกจากนี้การปิดด้วย RST ต่างจาก FIN เพราะยกเลิก connection ทันทีและอาจทำให้ข้อมูลที่ยังค้างสูญหาย

Half-Close และเหตุผลที่ EOF ไม่ใช่ข้อความว่างธรรมดา

เมื่อ recv() คืนศูนย์ byte บน TCP โดยไม่มี error โดยทั่วไปหมายถึง peer ปิดทิศส่งอย่างเป็นระเบียบ ไม่ได้หมายถึง “ยังไม่มีข้อมูล” Socket แบบ blocking จะรอ ส่วน nonblocking API ใช้สถานะหรือ error code แยกกรณี การเข้าใจ EOF ช่วยให้ server ไม่วนอ่านศูนย์ byteตลอดไป

Sliding Window ของ TCP — ทำหน้าที่ 3 อย่างพร้อมกัน

Invariant
Sender: LastByteAcked ≤ LastByteSent ≤ LastByteWritten
Receiver: LastByteRead < NextByteExpected ≤ LastByteRcvd + 1
AdvertisedWindow = MaxRcvBuffer − ((NextByteExpected−1) − LastByteRead)
Sequence Number Wraparound
TCP ใช้ sequence number 32 บิตและค่าจะวนกลับเมื่อส่ง byte จำนวนมาก Protocol ต้องแยก segment ใหม่จาก segment เก่าที่ยังค้างในเครือข่าย Window, TIME_WAIT และ TCP timestamps/PAWS ช่วยลดความกำกวมตามบริบท ค่า MSL และพฤติกรรมจริงขึ้นกับระบบ ไม่ควรใช้ 120 วินาทีเป็นค่าตายตัวของ Internet ทุกแห่ง

Triggering Transmission, Silly Window Syndrome, Nagle

TCP ตัดสินใจส่ง segment เมื่อ: (1) buffer ครบ MSS (2) application สั่ง push (3) timer หมดเวลา

Nagle's Algorithm
if (available data ≥ MSS) และ (window ≥ MSS): ส่งทันที
else:
    if มี unACKed data ค้างอยู่: buffer รอไว้
    else: ส่งทันที
Nagle ลด tiny segments จาก sender โดยให้มีข้อมูลเล็กที่ยังไม่ ACK ค้างได้เพียงชุดหนึ่ง แล้วรอ ACK หรือสะสมจนส่งก้อนใหญ่ขึ้น ช่วยลด overhead แต่ interaction กับ delayed ACK อาจเพิ่ม latency ในงานโต้ตอบ จึงมีกรณีใช้ TCP_NODELAY อย่างมีเหตุผล ไม่ใช่เปิดหรือปิดเป็นสูตรสำเร็จ

Silly Window Syndrome มีด้าน receiver ด้วย หาก receiver เปิด window ทีละน้อย ผู้ส่งอาจส่งชิ้นเล็กถี่ แนวทางอย่าง Clark's solution รอจนมีพื้นที่เพียงพอก่อน advertise window เพิ่ม Nagle แก้ tinygram ที่ sender ส่วนหนึ่ง แต่ไม่ได้เป็นคำตอบเดียวของ SWS ทั้งระบบ

Adaptive Retransmission (RTO)

Timeout สั้นเกินไปทำให้ retransmit ทั้งที่ packet เพียงมาช้า เพิ่มภาระให้เครือข่าย ส่วน timeout ยาวเกินไปทำให้ recovery ช้า TCP จึงประมาณ RTT จาก sample และเผื่อความผันผวน RTO ยังมีค่าต่ำสุด/สูงสุดและ exponential backoff ตาม implementation เพื่อไม่ให้ลองใหม่ถี่เมื่อเครือข่ายกำลังมีปัญหา

Algorithmสูตร/แนวคิดปัญหาที่แก้
OriginalTimeOut = 2×EstRTTRetransmission ambiguity: ACK ไม่รู้ว่ายืนยันรอบไหน
Karn/Partridgeไม่ sample RTT ตอน retransmit + double timeout ทุกครั้งที่ retransmitแก้ ambiguity แต่ยังไม่นับ variance
Jacobson/KarelsTimeOut = μ×EstimatedRTT + φ×Deviation (μ≈1, φ≈4)นำ variance เข้าสูตร — variance สูง timeout ยิ่งเผื่อมาก

Karn's algorithm ไม่ใช้ RTT sample จาก segment ที่ retransmit เพราะ ACK ที่กลับมาบอกไม่ได้ว่ายืนยันสำเนาแรกหรือสำเนาใหม่ หากเอาค่าคลุมเครือไปอัปเดต estimator อาจเรียน RTT ผิด ส่วน timestamp option ช่วยแยก sample ได้ดีขึ้นในหลายกรณี แต่รายละเอียดขึ้นกับ stack

ตั้ง Timeout เหมือนรอคนตอบโทรศัพท์
วางสายเร็วเกินไปก็โทรซ้ำทั้งที่อีกฝ่ายกำลังเดินมารับ รอนานเกินไปก็เสียเวลาเมื่อปลายสายไม่มีใครอยู่ ระบบจึงเรียนจากเวลาตอบในอดีตและความแกว่ง ไม่ใช้ค่าเฉลี่ยอย่างเดียว เพราะถ้าบางครั้งตอบเร็ว บางครั้งช้า ค่าเฉลี่ยอาจไม่เหมาะกับทั้งสองกรณี

Slow Start, Congestion Avoidance, Loss Recovery

AIMD
Slow Start: CW=1, +1 ทุก ACK (exponential ต่อ RTT) จนถึง ssthresh หรือเกิด loss
Congestion Avoidance: +1 ทุก RTT ที่ CW ทั้งก้อนถูก ACK (linear) — เมื่อ loss: ssthresh=CW/2 แล้ว CW/=2 (Fast Retransmit, TCP Reno) หรือ CW=1 (Coarse Timeout, กลับ slow start)

คำอธิบายนี้เป็นภาพของ TCP Reno เชิงตำราและใช้หน่วย MSS ในการอธิบาย ปัจจุบัน initial congestion window มักมากกว่า 1 MSS และระบบอาจใช้ CUBIC, BBR หรือ algorithm อื่น พฤติกรรมหลัง loss, ECN และ recovery จึงไม่เหมือนสูตร Reno ทุกประการ ควรเรียน Reno เพื่อเข้าใจ feedback loop แล้วแยกจาก implementation ที่เครื่องกำลังใช้

กลไกรายละเอียด
Coarse-grained Timeoutไม่ได้รับ ACK ตามเวลาที่คำนวณจาก RTT estimate (EWMA)
Fast Retransmitduplicate ACK 3 ครั้ง → สรุปว่า segment หาย → retransmit ทันที ไม่ต้องรอ timeout เต็มรอบ

Duplicate ACK สามครั้งเป็น heuristic ว่ายังมี packet หลังช่องว่างเดินทางถึง receiver จึงน่าจะมี segment หนึ่งหาย แต่ packet reordering ก็สร้าง duplicate ACK ได้ SACK option ให้ receiver รายงานช่วงข้อมูลที่ได้รับแล้ว ช่วยให้ sender รู้ช่องว่างหลายช่วงและ retransmit เจาะจงกว่าการพึ่ง cumulative ACK อย่างเดียว

Congestion Control ไม่เท่ากับ Flow Control

Receiver อาจ advertise window หลาย megabyte แต่ cwnd เล็กเพราะเครือข่ายเพิ่งมี loss ผู้ส่งต้องเคารพค่าที่เล็กกว่า ในทางกลับกัน network อาจโล่งและ cwnd ใหญ่ แต่ application ปลายทางอ่านช้าจน rwnd เหลือศูนย์ TCP ใช้ persist mechanism probe เพื่อหลีกเลี่ยง deadlock หาก window update หาย

Loss เป็นสัญญาณ ไม่ใช่คำอธิบายสาเหตุทั้งหมด
TCP แบบดั้งเดิมมักตีความ loss ว่า congestion แต่ wireless error, route change หรือ policer ก็ทำให้ loss ได้ ส่วนเครือข่ายมี buffer ใหญ่อาจ congestion โดยยังไม่ loss แต่ latency สูง ECN และ congestion algorithm รุ่นใหม่พยายามใช้สัญญาณอื่นร่วมด้วย

4RTP / RTCP — โปรโตคอลสำหรับสื่อ Real-Time

ตำแหน่งของ RTP
RTP โดยทั่วไปวิ่งเหนือ UDP และเพิ่ม sequence number, timestamp, payload type และ source identifier สำหรับสื่อ real-time แต่ RTP ไม่จอง bandwidth ไม่รับประกัน delivery และไม่ลด jitter ด้วยตัวเอง Application ใช้ข้อมูลเหล่านี้สร้าง jitter buffer ตรวจ loss และจัด playback
Field ใน RTP Headerความหมาย
Sequence numberช่วยตรวจ packet loss, duplicate และเรียง packet; ไม่ได้กำจัด jitter ด้วยตัว field เอง
Timestampเวลา sampling — synchronize packet จากหลายแหล่ง
SSRCระบุ synchronization source ภายใน RTP session โดยเลือกค่าให้มีโอกาสชนต่ำและมีกลไกจัดการ collision ไม่ใช่ identity ถาวรของ device

RTCP รายงานคุณภาพผ่าน Sender/Receiver Report เช่น packet count, loss, highest sequence, interarrival jitter และ timing information Jitter estimator ของ RTP สะท้อนความแปรผันของ transit time ระหว่าง packet ต่อเนื่อง ไม่ใช่ delay เฉลี่ย และ receiver ยังต้องเลือกขนาด jitter buffer แลกระหว่างการเล่นราบรื่นกับ latency

Jitter Buffer เหมือนพิธีกรรอคิวแขกก่อนขึ้นเวที
ถ้าปล่อยแขกขึ้นทันทีที่มาถึง คนที่รถติดเล็กน้อยทำให้รายการสะดุด ถ้ารอรวบทุกคนไว้นาน รายการลื่นแต่ถ่ายทอดช้ากว่าความจริง Buffer จึงดูดซับความแกว่งด้วยต้นทุน latency ไม่มีค่าที่ดีที่สุดสำหรับทั้งการโทรโต้ตอบและการชมวิดีโอแบบไม่โต้ตอบ

5QUIC — Transport สมัยใหม่ที่สร้างใน User Space

QUIC ทำงานบน UDP เพื่อให้พัฒนาและ deploy transport logic ใน user space ได้เร็วกว่าแก้ TCP ใน kernel และ middlebox ทั่วโลก แต่ QUIC สร้าง reliability, congestion control, flow control และ connection management ของตนเอง พร้อมผสาน TLS 1.3 การอยู่บน UDP จึงไม่ได้ทำให้ QUIC เป็น unreliable protocol

TCP มี byte stream เดียว หาก packet ของ stream ขาด byte ต่อไปทั้งหมดต้องรอลำดับ แม้ application มีหลาย logical request HTTP/2 multiplex หลาย stream บน TCP แต่ packet loss ยังทำให้ transport stream ทั้ง connection รอ QUIC มี stream หลายชุดและ loss ของ stream หนึ่งไม่จำเป็นต้องบล็อก delivery ของ stream อื่นในระดับเดียวกัน แม้ congestion control ยังร่วมทรัพยากร connection

QUIC ใช้ Connection ID ช่วยให้ connection อยู่ต่อเมื่อ IP address หรือ port เปลี่ยน เช่นย้ายจาก Wi‑Fi ไป cellular ภายใต้นโยบายและการตรวจ path แต่ mobility ไม่ได้ไร้ความเสี่ยงหรือสำเร็จทุกกรณี Server และ network ยังต้องรองรับ การเปลี่ยน path อาจเปลี่ยน RTT/MTU และต้อง validate address เพื่อป้องกัน amplification

Protocol Stack ไม่ได้หยุดนิ่งตามชั้นในตำรา
QUIC วาง transport semantics บน UDP และรวม security handshake ไว้ใกล้กัน แสดงว่าการแบ่งชั้นเป็นเครื่องมืออธิบายความรับผิดชอบ ไม่ใช่คำสั่งว่าซอฟต์แวร์ต้องอยู่ไฟล์ใดหรือ kernel เท่านั้น สิ่งสำคัญคือรู้ว่าคุณสมบัติถูกสร้างที่ไหนและ failure boundary อยู่ตรงใด

6Socket API: ประตูสู่ Transport Layer

Transport service ที่แอปพลิเคชันเรียกผ่าน socket ต้องการต่างกันตามชนิดแอป:

ApplicationData LossTime Sensitive
File transfer / e-mail / Webno lossno
Real-time audio/videoloss-tolerantyes, ~100 ms
Interactive gamesloss-tolerantyes, ~100 ms

ตารางเป็นภาพรวม ไม่ใช่กฎตายตัว Web สมัยใหม่อาจมี latency requirement สูงและใช้ QUIC ส่วน file transfer อาจยอม resume แทนเริ่มใหม่ Real-time media บางข้อมูล เช่น control message สำคัญกว่าภาพบาง frame Application จึงควรแยกชนิดข้อมูลและ deadline ไม่ตัดสิน protocol จากชื่อหมวดเพียงอย่างเดียว

UDP Socket

# Python UDP Client
clientSocket = socket(AF_INET, SOCK_DGRAM)
clientSocket.sendto(message,(serverName, serverPort))
modifiedMessage, serverAddress = clientSocket.recvfrom(2048)

# Python UDP Server
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', serverPort))
while 1:
    message, clientAddress = serverSocket.recvfrom(2048)
    serverSocket.sendto(message.upper(), clientAddress)

TCP Socket

# Python TCP Client
clientSocket = socket(AF_INET, SOCK_STREAM)
clientSocket.connect((serverName,serverPort))
clientSocket.send(sentence)
modifiedSentence = clientSocket.recv(1024)

# Python TCP Server
serverSocket = socket(AF_INET,SOCK_STREAM)
serverSocket.bind(('',serverPort)); serverSocket.listen(1)
while 1:
    connectionSocket, addr = serverSocket.accept()
    sentence = connectionSocket.recv(1024)
    connectionSocket.send(sentence.upper())
    connectionSocket.close()

ตัวอย่างเป็น pseudocode แบบ Python รุ่นเก่าเพื่อเน้นลำดับ API ใน Python 3 ข้อมูลที่ส่งผ่าน socket เป็น bytes จึงต้อง encode/decode ตาม format ที่ตกลง และ send() อาจส่งได้เพียงบางส่วนของ buffer ควรใช้ sendall() หรือวนจัดการจำนวน byte ที่ส่งจริง ส่วน recv(1024) หมายถึงรับได้ไม่เกิน 1,024 byte ไม่ได้สัญญาว่าจะได้ครบหนึ่ง message

send() สำเร็จ เหมือนเคาน์เตอร์รับพัสดุแล้ว
ระบบปฏิบัติการรับ byte เข้า send buffer ไม่ได้หมายความว่า peer application อ่านแล้วหรือทำ transaction สำเร็จ ถ้าต้องการยืนยันระดับธุรกิจ เช่นตัดเงินแล้ว ต้องมี application response, request ID และ idempotency ไม่ควรใช้ TCP ACK เป็นใบเสร็จของงานระดับ application

TCP Server มี Listening Socket กับ Connected Socket คนละหน้าที่

listen() เปลี่ยน socket ให้รับ connection request ส่วน accept() คืน connected socket ใหม่สำหรับ client หนึ่งราย Listening socket เดิมยังอยู่เพื่อรับ client ถัดไป Server จึงมี local port เดียวแต่ connection หลายชุดแยกด้วย tuple การปิด connected socket ไม่ควรปิด listening socket เว้นแต่จะหยุดบริการ

Server ตัวอย่างรับทีละ client ถ้า client หนึ่งช้าจะบล็อกคนอื่น ระบบจริงใช้ thread, process, event loop หรือ asynchronous I/O พร้อมจำกัด concurrency และ timeout การทำ concurrent server ไม่ได้เพิ่ม capacity แบบไม่จำกัด เพราะ file descriptor, memory, CPU และ downstream service ยังเป็นทรัพยากรที่ต้องควบคุม

จุดต่างที่มักออกข้อสอบ
UDP ต้องดึง address จาก packet ทุกครั้ง (recvfrom) เพราะไม่มี "connection" ผูกไว้ / TCP หลัง accept() แล้ว อ่าน-เขียนผ่าน socket ที่ผูกกับ client ตัวนั้นได้เลย — ดูตัวอย่างการใช้งานโปรโตคอลเหล่านี้จริงในหน้า Application Layer (HTTP/FTP/DNS)

UDP socket สามารถเรียก connect() ได้เช่นกัน แต่ไม่ได้สร้าง handshake แบบ TCP มันกำหนด default peer และช่วยกรอง/รายงาน error ผ่าน API บางส่วน จึงควรพูดว่า UDP ไม่มี transport connection state แบบ TCP มากกว่าจะบอกว่า UDP “connect ไม่ได้” โดยเด็ดขาด

7Partial Failure, Timeout และ Idempotency

ระบบเครือข่ายมีความกำกวมที่โปรแกรมเครื่องเดียวพบไม่บ่อย Client ส่ง request แล้ว connection ขาดก่อนเห็น response เราไม่รู้ว่า request ไม่ถึง, server กำลังทำ, ทำเสร็จแต่ response หาย หรือทำเสร็จแล้ว server ล่ม การ timeout บอกเพียงว่าไม่มีผลลัพธ์ในเวลาที่รอ ไม่ได้บอกว่างานไม่เกิด

สั่งอาหารแล้วสายหลุด
หลังบอกเมนู สายตัดก่อนร้านตอบ ถ้าโทรสั่งใหม่อาจได้สองชุด ถ้าไม่โทรอาจไม่ได้เลย Transport reliability ลดโอกาส byte หายระหว่าง connection แต่ไม่สามารถตัดสิน transaction หลัง connection ขาดแทน application ได้ Request ID และ idempotency key คล้ายเลขออร์เดอร์ที่ทำให้ร้านรู้ว่าสายใหม่เป็นงานเดิม

Retry ต้องมี Budget และ Backoff

Retry ช่วยจาก transient failure แต่ถ้า client จำนวนมากลองใหม่ทันทีเมื่อ server ช้า ภาระจะเพิ่มจนระบบฟื้นยาก เกิด retry storm Exponential backoff กระจายเวลาลองใหม่และ jitter ลดการตื่นพร้อมกัน แต่ต้องจำกัดจำนวนครั้ง/เวลารวม และพิจารณา deadline ของผู้ใช้ด้วย

คำถามก่อน Retryเหตุผล
Operation idempotent หรือไม่GET มักลองซ้ำได้ แต่ charge payment ซ้ำอาจสร้างผลลัพธ์สองครั้งหากไม่มี key
Failure ชนิดใดTimeout อาจชั่วคราว แต่ authentication error หรือ malformed request ไม่ดีขึ้นจากการลองเดิม
เหลือ deadline เท่าไรRetry ที่เสร็จหลังผู้ใช้เลิกสนใจเป็นภาระที่ไม่มีคุณค่า
ใครกำลัง retry อีกหลายชั้น retry ซ้อนกันทำให้จำนวนคำขอคูณแบบไม่ตั้งใจ
Exactly-once เป็นคุณสมบัติระดับระบบ ไม่ใช่ของ TCP
TCP ส่ง byte ตามลำดับใน connection แต่ application request อาจถูกส่งใหม่หลัง reconnect Exactly-once effect ต้องอาศัย identity, durable state, deduplication และ transaction boundary ที่ชัด การเขียนว่า “ใช้ TCP จึงไม่ซ้ำ” เป็นการข้ามระดับของปัญหา

8การวิเคราะห์ปัญหา Transport Layer

อาการ “ต่อไม่ได้” ควรถูกแยกเป็น DNS/IP path, connection establishment, TLS/application และ server capacity ถ้า SYN ออกแต่ไม่มี SYN-ACK อาจเป็น route, firewall, server ไม่ฟัง หรือ response กลับคนละทาง ถ้าได้ RST มักมี node ตอบปฏิเสธอย่างชัดเจน เช่นไม่มี listener หรือ policy ส่ง reset ส่วน timeout คือความเงียบที่มีหลายคำอธิบาย

หลักฐานตีความเบื้องต้นข้อควรระวัง
SYN retransmissionHandshake ยังไม่ได้คำตอบที่ยอมรับไม่บอกว่า packet ขาไปหรือคำตอบขากลับหาย
RSTConnection ถูกปฏิเสธ/ยกเลิกโดย endpoint หรือ middleboxต้องดู sequence และตำแหน่งผู้ส่ง ไม่เหมารวมว่า server ล่ม
Duplicate ACK/SACKReceiver เห็นช่องว่างหรือ reorderingไม่เท่ากับ congestion เสมอไป
Zero WindowReceiver buffer ไม่มีพื้นที่เพิ่มชี้ว่า application ฝั่งรับอาจอ่านไม่ทัน ไม่ใช่ network bandwidth ต่ำ
Retransmission timeoutACK ไม่มาตาม RTOสาเหตุอาจเป็น loss, delay spike, path change หรือ endpoint stall

ss/netstat ช่วยดู socket state และ queue, packet capture ช่วยเห็น flags, sequence, ACK และ timing, application log ช่วยตอบว่าข้อมูลถูกอ่านและประมวลผลหรือไม่ ต้องใช้ร่วมกัน เพราะ packet capture เห็น ACK ระดับ kernel แต่ไม่เห็นว่า application ทำงานสำเร็จ

TIME_WAIT, CLOSE_WAIT และความหมายที่ต่างกัน

TIME_WAIT จำนวนมากอาจเป็นผลปกติของ endpoint ที่ active close connection บ่อย ไม่ใช่ memory leak โดยอัตโนมัติ ส่วน CLOSE_WAIT หมายถึง local application ได้รับ FIN แล้วแต่ยังไม่ปิด socket หากสะสมมากมักชี้ว่าโปรแกรมไม่จัดการ close หลัง peer ปิด การแก้ด้วยการลด timeout โดยไม่เข้าใจ state อาจซ่อนอาการและเสี่ยง segment เก่าปะปน

TCP State เหมือนสถานะงานเอกสาร
“ส่งแล้ว”, “อีกฝ่ายรับแล้ว”, “อีกฝ่ายปิดเรื่องแล้ว” และ “เก็บแฟ้มรอหมดอายุ” เป็นคนละสถานะ การเห็นแฟ้มจำนวนมากไม่ได้แปลว่าเจ้าหน้าที่ค้างงานทุกใบ ต้องอ่านว่าค้างที่ขั้นใดจึงรู้ว่าควรแก้ผู้ส่ง ผู้รับ หรือระยะเวลาเก็บหลักฐาน

9ความปลอดภัยและขอบเขตของ Transport

TCP และ UDP checksum ตรวจความเสียหายจากการส่ง ไม่ใช่ cryptographic integrity ผู้โจมตีสามารถแก้ payload แล้วคำนวณ checksum ใหม่ได้ TLS จึงสร้าง confidentiality, authentication และ integrity เหนือ transport ตาม configuration แต่ TLS ไม่ซ่อน IP address และ traffic timing ทั้งหมด และไม่แก้ denial-of-service ทุกชนิด

Port scanning ใช้พฤติกรรม SYN, RST หรือ ICMP อนุมานว่าบริการใดเปิด Firewall อาจ drop ให้ timeout หรือ reject ด้วย response ผลลัพธ์จึงบอกสิ่งที่ scanner มองเห็นจากจุดนั้น ไม่ใช่รายการ process ที่เครื่องมีทั้งหมด การเปิด port ก็ไม่ได้แปลว่ามีช่องโหว่ แต่เพิ่ม attack surface ที่ต้องอัปเดตและกำหนดสิทธิ์

TCP reset injection และ sequence prediction เป็นเหตุผลที่ initial sequence number ต้องคาดเดายากพอใน threat model แม้ TLS ปกป้อง application data ได้ดีกว่า Transport security ต้องมองทั้ง endpoint authentication, key management, protocol version และ implementation ไม่ยกภาระทั้งหมดให้คำว่า connection-oriented

10ออกแบบ Protocol บน TCP ให้ไม่พังตรงขอบเขต Message

ข้อผิดพลาดที่พบซ้ำใน lab คือ client ส่ง JSON หนึ่งครั้ง แล้ว server เรียก recv(1024) หนึ่งครั้งและสมมุติว่าได้ JSON ครบ วิธีนี้อาจทำงานบนเครื่องเดียวกันในข้อความสั้น ๆ จนดูเหมือนถูก แต่ TCP มีสิทธิ์แบ่งข้อมูลเป็นหลาย segment รวมหลาย write ใน buffer เดียว หรือให้ recv() คืนเท่าที่มีตอนนั้น การทดสอบที่เครือข่ายเร็วและโหลดต่ำเพียงซ่อน bug ไว้ให้ไปเปิดตัวใน production

วิธีสร้าง Message Framing ที่ใช้บ่อย

วิธีหลักการจุดที่ต้องระวัง
Delimiterปิดท้าย message ด้วย newline หรือ sentinelต้อง escape delimiter ใน payload, จำกัดความยาว และรับมือกรณี delimiter ยังมาไม่ถึง
Length Prefixส่งความยาวคงรูปก่อน payloadต้องตกลง byte order, ขนาด field และปฏิเสธ length ใหญ่ผิดปกติก่อนจอง memory
Fixed Lengthทุก record มีขนาดเท่ากันง่ายแต่สิ้นเปลืองเมื่อข้อมูลแปรผันและเปลี่ยน schema ยาก
Self-describing FormatParser รู้จุดจบจาก grammar เช่นบางรูปแบบของ encodingยังต้องรองรับ incremental parsing และ depth/size limit ไม่ใช่เรียก parse กับ buffer ที่ยังไม่ครบ
Length Prefix แบบคิดเป็น State Machine
  1. สะสมข้อมูลจนได้ header ความยาวครบ 4 byte
  2. แปลง network byte order เป็นจำนวน N และตรวจว่าไม่เกิน limit
  3. สะสม payload จนครบ N byte แม้ต้องเรียก recv() หลายรอบ
  4. ส่ง message ให้ parser แล้ววนอ่าน header ของ message ถัดไปจาก byte ที่ยังเหลือใน buffer

ถ้า recv() ได้ท้าย message แรกพร้อมต้น messageที่สอง ห้ามทิ้ง byte ส่วนเกิน State machine ต้องเก็บไว้ใช้รอบถัดไป นี่คือเหตุผลที่ protocol parser ควรแยกจากการเรียก socket โดยตรง

TCP ส่งตัวอักษรต่อกันเหมือนม้วนกระดาษ
ผู้ส่งเขียนจดหมายสองฉบับต่อบนม้วนเดียว คนส่งอาจตัดม้วนเป็นท่อนตามที่ขนสะดวก ผู้รับต้องอ่านเลขความยาวหรือเครื่องหมายจบจึงรู้ขอบเขต ไม่สามารถเดาจากรอยตัดของรถขนส่ง เพราะรอยตัดนั้นเป็นเรื่องของ TCP segment และ buffer ไม่ใช่โครงสร้างของจดหมาย

ป้องกัน Slow Client และข้อความที่ประกาศความยาวเกินจริง

ผู้โจมตีอาจส่ง header ช้ามากหรือประกาศ payload หลาย gigabyte แล้วไม่ส่งต่อ หาก server จอง memory ทันทีหรือเก็บ connection ไม่จำกัดจะเกิด denial of service ต้องมี maximum message size, read timeout, idle timeout, connection limit และการจัดสรร buffer แบบระวัง แต่ timeout สั้นเกินไปอาจตัดผู้ใช้เครือข่ายช้า จึงต้องเลือกจาก workload และวัดผล

Serialization ไม่ใช่ Framing
JSON บอกวิธีแทน object เป็น byte แต่ไม่ได้ทำให้ TCP รู้ว่า JSON หนึ่งก้อนจบตรงไหนเสมอไป โดยเฉพาะเมื่อส่งต่อกันหลายก้อน ต้องแยก representation, framing และ transport reliability ออกจากกัน แล้วออกแบบแต่ละส่วนให้ครบ

11Connection Reuse, Pooling และต้นทุนที่ซ่อนอยู่

การเปิด TCP connection ใหม่มี handshake และอาจมี TLS handshake, authentication และ warm-up ของ congestion window การ reuse connection ลด latency และ CPU แต่ connection ที่เปิดค้างใช้ file descriptor, memory, state ใน load balancer/NAT และอาจชี้ไป backend ที่ไม่เหมาะแล้ว Connection pooling จึงต้องกำหนดขนาด อายุ idle, max lifetime และวิธีตรวจ connection ที่ถูกปิดจากอีกฝั่ง

Connection Pool เหมือนเก็บรถแท็กซี่รอไว้หน้าอาคาร
มีรถพร้อมใช้ช่วยไม่ต้องเรียกใหม่ทุกเที่ยว แต่ถ้าเก็บไว้ร้อยคันโดยไม่มีผู้โดยสารก็เปลืองพื้นที่ รถที่จอดนานอาจน้ำมันหมดหรือใบอนุญาตหมดอายุ Pool ที่ดีไม่ได้มี connection มากที่สุด แต่มีพอเหมาะและรู้ว่าคันไหนยังใช้งานได้

Keepalive มีหลายความหมาย

TCP keepalive เป็นกลไก OS ตรวจ peer ที่เงียบตาม timer ซึ่งมักมีค่าเริ่มต้นยาวและปรับได้ HTTP keep-alive หมายถึง reuse connection สำหรับหลาย request ส่วน application heartbeat เป็นข้อความตาม protocol เพื่อบอก health หรือ lease ทั้งสามอย่างไม่เหมือนกัน การเปิด TCP keepalive ไม่ได้แทน application heartbeat ที่ต้องตรวจว่า service loop ยังตอบได้

Connection ที่ขาดแบบเงียบอาจไม่ถูกตรวจจนมีการส่งข้อมูล เพราะ TCP ไม่มีข้อความลอยมาแจ้งทันทีว่า router กลางทางหาย Application ที่ต้องรู้สถานะเร็วต้องมี deadline/heartbeat แต่ heartbeat ถี่เกินไปเพิ่ม traffic และอาจประกาศ failure จาก network pause ชั่วคราว จึงควรผูกกับ recovery objective ที่ต้องการ

Head-of-Line Blocking

TCP ต้องส่ง byte ให้ application ตามลำดับ ถ้า segment หนึ่งหาย byte หลังจากนั้นที่มาถึงแล้วต้องรอช่องว่าง แม้เป็นข้อมูลคนละ logical request บน connection เดียว HTTP/2 multiplex ลดการรอระดับ application framing แต่ยังอยู่บน TCP stream เดียว QUIC แยก stream จึงลด transport head-of-line blocking ข้าม streamได้ อย่างไรก็ตาม packet loss ยังลด congestion window และกระทบ capacity รวม

Connection น้อยไม่ได้แปลว่าเร็วกว่าเสมอ และมากก็ไม่ได้แปลว่าขนานได้ฟรี
Connection เดียวอาจติด head-of-line หรือใช้ core ไม่เต็ม แต่ connection จำนวนมากแข่งขันกัน สร้าง handshake/state และอาจไม่เป็นธรรมกับ flow อื่น การเลือกจำนวนต้องวัด latency, throughput, resource และ downstream limit พร้อมกัน

12Performance ของ Transport: BDP, Window Scale และ Application Backpressure

ลิงก์ bandwidth สูงและ RTT ยาวต้องมีข้อมูลค้างระหว่างทางมากพอจึงใช้ capacity เต็ม Bandwidth-delay product ประมาณจาก bandwidth × RTT เช่น 1 Gb/s กับ RTT 100 ms มี BDP 100 Mb หรือ 12.5 MB ถ้า effective window เพียง 64 KB throughput จะติดที่ window/RTT แม้ลิงก์ว่างมาก

TCP Window Scale option ขยาย receive window เกิน field 16 บิตและต้องเจรจาตอน SYN ส่วน congestion window ต้องเติบโตตาม algorithm ด้วย การเพิ่ม socket buffer อย่างเดียวจึงไม่รับประกัน throughput ถ้า loss สูง, application เขียนไม่ทัน, cwnd เล็ก หรือ path มี bottleneck ต่ำกว่า

คำนวณ Window ที่ต้องการคร่าว ๆ

ต้องการ 200 Mb/s บนเส้นทาง RTT 80 ms: 200,000,000 × 0.08 = 16,000,000 bit ≈ 2 MB จึงต้องมีข้อมูล in flight ราว 2 MB เพื่อแตะอัตรานั้นภายใต้เงื่อนไขง่าย ๆ Window ต่ำกว่านี้เป็นเพดานก่อนคิด loss และ overhead

Backpressure ต้องเดินจากปลายทางกลับถึงต้นทาง

TCP flow control หยุด sender เมื่อ receive buffer เต็ม แต่ถ้า application server อ่านเข้าหน่วยความจำเร็วแล้วโยนงานเข้า queue ภายในไม่จำกัด TCP จะเห็น receiver ว่าง ขณะที่ระบบจริงกำลังสะสมงาน Backpressure ที่ดีต้องเชื่อม queue ของ application, worker, database และ upstream ไม่ใช่หยุดที่ socket buffer

Async framework ทำให้รับ connection จำนวนมากได้ แต่ไม่ได้ทำให้ CPU/database ทำงานพร้อมกันไม่จำกัด หากอ่าน request ทุกตัวเข้ามาแล้วสร้าง task โดยไม่จำกัด ระบบอาจใช้ memory จนล้ม Semaphore, bounded queue, admission control และ response อย่าง overload เป็นส่วนต่อของ flow control ในระดับ service

TCP ปิดก๊อกที่ถังหน้าโรงงาน แต่ไม่เห็นโกดังข้างใน
ถ้าคนงานรีบตักน้ำออกจากถัง TCP จะคิดว่ายังรับได้ แม้เอาน้ำไปกองในถังภายในจนล้น Application ต้องส่งสัญญาณความแน่นย้อนกลับเอง Transport มองเห็นเพียง buffer ที่รับผิดชอบ ไม่ได้รู้ workload ทั้งระบบ

Timeout ควรแยกตามช่วง ไม่ใช้ตัวเลขเดียวครอบทุกอย่าง

โปรแกรมหนึ่ง request มีได้ทั้ง DNS timeout, connect timeout, TLS handshake timeout, time-to-first-byte, read timeout และ deadline รวม ถ้าใช้ read timeout 30 วินาทีอย่างเดียว DNS อาจค้างเกือบทั้งหมดจนไม่เหลือเวลาให้ server ทำงาน ในทางกลับกัน deadline รวมที่ไม่มี timeout ย่อยอาจทำให้เราไม่รู้ว่าค้างขั้นใด

เวลาขอบเขตที่กำลังรอ
Connect timeoutรอ transport connection establishment ไม่รวมงาน application หลังเชื่อมแล้ว
Read/idle timeoutรอความคืบหน้าของข้อมูล อาจ reset เมื่อมี byte ใหม่ตาม semantics ของ library
Request deadlineเวลารวมที่งานยังมีคุณค่าสำหรับ caller ควรถูกส่งต่อไป downstream เท่าที่ระบบรองรับ
Retry budgetเวลาหรือจำนวนความพยายามรวม ไม่ให้ retry แต่ละชั้นใช้ deadline จนหมดซ้ำกัน

การเลือก timeout ควรดู latency distribution และผลของ false timeout ไม่ใช้ค่าเฉลี่ยเพียงอย่างเดียว Tail latency ทำให้ request บางส่วนช้ากว่าปกติ การตั้งต่ำเกิน percentile ที่ระบบให้ได้จะสร้าง retry จาก request ที่เกือบสำเร็จ และ retry เหล่านั้นผลักระบบให้ช้าลงอีก นี่เป็น feedback loop ที่เริ่มจากตัวเลข timeout ตัวเดียวได้

Timeout เป็นการตัดสินใจของผู้รอ ไม่ใช่สถานะของผู้ถูกเรียก
เมื่อ client หมดเวลา server อาจยังทำงานต่อ หากไม่ส่ง cancellation หรือ server ไม่รองรับ การมี deadline propagation และ cooperative cancellation ช่วยลดงานไร้เจ้าของ แต่ operation ที่เริ่ม side effect แล้วต้องออกแบบ cleanup และ idempotency แยกต่างหาก

13สรุปและขั้นตอนถัดไป

  • Transport Layer เปลี่ยน host-to-host delivery เป็น process-to-process communication ผ่าน port และ socket
  • UDP รักษาขอบเขต datagramและเพิ่ม checksum แต่ไม่สร้าง retransmission, ordering, flow control หรือ congestion control ให้ application
  • TCP เป็น reliable ordered byte stream ไม่รักษาขอบเขต message Application ต้องออกแบบ framing เอง
  • TCP sequence number นับ byte, ACK เป็น cumulative และข้อมูลที่ส่งได้ถูกจำกัดโดยทั้ง receive window กับ congestion window
  • Flow control ปกป้อง receiver ส่วน congestion control ปกป้องเครือข่าย เป็น feedback คนละแหล่งแม้ใช้ window ร่วมกัน
  • RTO ต้องเรียนทั้ง RTT และความผันผวน Karn หลีกเลี่ยง ambiguous sample ส่วน Jacobson/Karels นำ deviation มาคิด
  • Nagle ลด tiny segments ฝั่งส่ง ส่วนปัญหา receiver เปิด window ทีละน้อยต้องใช้แนวทางอีกด้านและอาจเกิด interaction กับ delayed ACK
  • Reno อธิบาย slow start, AIMD และ loss recovery เชิงพื้นฐาน แต่ TCP สมัยใหม่อาจใช้ CUBIC, BBR หรือ algorithm อื่น
  • RTP ให้ sequence/timestamp สำหรับ application จัด playback ส่วน RTCP รายงานคุณภาพ ไม่ได้จอง bandwidth หรือกำจัด jitter เอง
  • QUIC สร้าง reliable secure multi-stream transport บน UDP แสดงว่าคุณสมบัติ transport ไม่ได้ผูกกับตำแหน่งใน kernel เพียงแบบเดียว
  • Timeout ไม่ได้พิสูจน์ว่างานไม่เกิด Retry ต้องคิด idempotency, backoff, jitter และ deadline
  • TCP ACK ยืนยัน byte ระดับ transport ไม่ใช่หลักฐานว่า transaction ระดับ application สำเร็จ
คำถามซ้อมสอบ
  1. เขียน invariant ของ sliding window ทั้งสองฝั่งพร้อมอธิบายความหมาย
  2. เปรียบเทียบ Karn/Partridge กับ Jacobson/Karels
  3. อธิบายกลไก AIMD และเหตุผลที่ใช้ additive increase แต่ multiplicative decrease
  4. อธิบาย fast retransmit และเกณฑ์ duplicate ACK 3 ครั้ง
  5. อธิบายว่าทำไมการเรียก send() สองครั้งไม่รับประกันว่า peer จะ recv() ได้สอง message
  6. เปรียบเทียบ rwnd กับ cwnd และวิเคราะห์กรณี zero window กับ congestion loss
  7. อธิบาย TIME_WAIT กับ CLOSE_WAIT และระบุว่า application ฝั่งใดควรตรวจเมื่อ state สะสม
  8. ออกแบบ retry ของคำสั่งชำระเงินโดยใช้ idempotency key, deadline และ backoff

ขั้นตอนถัดไปในเส้นทาง OSI คือ Session Layer ซึ่งถามเรื่องการรักษาบริบทของการสนทนา การแบ่งช่วง และการกลับมาทำงานต่อ แต่ใน TCP/IP stack หน้าที่เหล่านี้มักอยู่ใน application protocol, library หรือ service state ไม่ได้มี Session protocol กลางหนึ่งตัวคั่นอยู่เหนือ TCP ทุกครั้ง การเรียนชั้นถัดไปจึงควรมองเป็นชุดความรับผิดชอบ ไม่ใช่ตามหา header ชื่อ Session ในทุก packet

Transport ส่งบทสนทนาได้ แต่ยังไม่รู้ว่าคุยเรื่องอะไร
TCP ช่วยให้ถ้อยคำมาครบตามลำดับ แต่ไม่รู้ว่าผู้ใช้ login อยู่หรือไม่ งานนี้เป็นหน้าใด หรือถ้าหลุดแล้วควรเริ่มต่อจาก checkpoint ไหน Session และ Application logic จะเพิ่มบริบทเหล่านั้น ความน่าเชื่อถือของ byte จึงเป็นฐานสำคัญ แต่ยังไม่ใช่ความถูกต้องของกระบวนงานทั้งหมด