ข้ามไปยังเนื้อหา

WebSocket vs SSE vs WebTransport

WebSocket เป็น transport สำหรับ real-time ที่ มีความสามารถ มากที่สุด แต่ความสามารถไม่เหมือนกับความเหมาะสม รอบ ๆ WebSocket ยังมีทางเลือกอีกสามแบบ แต่ละแบบยอมแลกพลังบางส่วนทิ้งไปเพื่อความเรียบง่าย ความเข้ากันได้ หรือความเร็วล้วน ๆ การรู้ว่าแต่ละแบบชนะตรงไหนช่วยให้คุณไม่ต้องแบก full duplex socket — พร้อมกลไก reconnection, heartbeat และ auth ที่ตามมา — ทั้งที่ของเบากว่าก็พอใช้แล้ว

  • WebSocket — การเชื่อมต่อเดียว ถาวร และ สองทาง ฝั่งใดก็ส่ง message ได้ทุกเมื่อ เรียงลำดับและเชื่อถือได้ เป็นค่าตั้งต้นเมื่อ traffic ไหลทั้งสองทางจริง ๆ: แชต การทำงานร่วมกัน multiplayer คำสั่งแบบสด
  • Server-Sent Events (SSE) — HTTP response ที่อยู่ยาวซึ่ง stream event ที่เป็น text จาก server → client เท่านั้น client ส่งย้อนกลับทางเดิมไม่ได้ (ต้องใช้ HTTP request ธรรมดาแทน) แลกมาด้วยความเรียบง่ายสุด ๆ วิ่งบน HTTP ธรรมดา และ EventSource ของเบราว์เซอร์ reconnect ให้อัตโนมัติ แล้วต่อยอดจาก event id ล่าสุด เหมาะสำหรับ feed: การแจ้งเตือน dashboard ticker ราคา progress log
  • Long-polling — ไม่ใช่ transport แบบ stream จริง ๆ แต่เป็น fallback client ส่ง HTTP request แล้ว server ถือ request นั้นค้างไว้จนกว่าจะมีอะไรจะพูด ตอบกลับ แล้ว client ก็ขอใหม่ทันที วิธีนี้ทำงานได้ผ่าน proxy หรือ stack เก่าแก่แทบทุกแบบ โดยแลกกับ latency และ overhead ไลบรารีมักใช้เป็นการลดระดับอย่างนุ่มนวลเมื่อ WebSocket หรือ SSE โดนบล็อก
  • WebTransport — น้องใหม่ สร้างบน HTTP/3 (QUIC) ให้ทั้ง stream ที่เชื่อถือได้และเรียงลำดับ และ datagram ที่ไม่เชื่อถือได้และไม่เรียงลำดับ บนการเชื่อมต่อเดียว พร้อม multiplexing ที่หลีกเลี่ยง head-of-line blocking มุ่งเป้าไปที่ media และเกมความถี่สูงและไวต่อ latency ที่การทิ้งแพ็กเก็ตเก่าดีกว่าการรอ retransmit ยังใหม่กว่า WebSocket และยังไม่รองรับทั่วทุกที่

การตัดสินใจมักหลุดออกมาจากสองคำถาม: ข้อมูลไหลในทิศทางใดบ้าง และ traffic ทนต่อการสูญหายเพื่อแลกกับความเร็วได้หรือไม่?

flowchart TD
  q1["Does the client need to send<br/>messages mid-connection?"]
  q1 -- "No — server pushes only" --> q2["Need to resume a stream<br/>and reconnect for free?"]
  q2 -- "Yes, and plain HTTP is fine" --> sse["Server-Sent Events"]
  q2 -- "Legacy proxies break streaming" --> poll["Long-polling fallback"]
  q1 -- "Yes — both directions" --> q3["High-frequency media, or<br/>OK to drop stale packets?"]
  q3 -- "No — ordered, reliable messages" --> ws["WebSocket"]
  q3 -- "Yes — datagrams / low latency" --> wt["WebTransport (HTTP/3)"]
ขั้นตอนการตัดสินใจเลือก transport สำหรับ real-time

อ้างอิงอย่างรวดเร็ว เทียบกันแบบเคียงข้าง:

| Transport | ทิศทาง | Protocol | Auto-reconnect | การส่ง | เหมาะที่สุดสำหรับ | | --- | --- | --- | --- | --- | | WebSocket | สองทาง | TCP, HTTP Upgrade | คุณสร้างเอง | เรียงลำดับ เชื่อถือได้ | แชต การทำงานร่วมกัน คำสั่ง | | SSE | server → client | HTTP (text/event-stream) | มีในตัว (EventSource) | เรียงลำดับ เชื่อถือได้ | feed การแจ้งเตือน dashboard | | Long-polling | วน request/response | HTTP | ไม่มี (ขอใหม่) | เชื่อถือได้ latency สูงกว่า | fallback ผ่าน proxy เก่า | | WebTransport | สองทาง | HTTP/3 (QUIC) | คุณสร้างเอง | stream หรือ datagram | เกม media แบบ real-time |

ข้อเท็จจริงไม่กี่อย่างที่เปลี่ยนการออกแบบจริง:

  • SSE มีงบประมาณการเชื่อมต่อต่อ origin. บน HTTP/1.1 เบราว์เซอร์จำกัดจำนวนการเชื่อมต่อพร้อมกันต่อ host (โดยทั่วไปคือหก) และ EventSource ที่อยู่ยาวกินไปหนึ่ง การเปิดหลายแท็บไปยัง origin เดียวกันอาจใช้โควตาจนหมด บน HTTP/2 ขีดจำกัดนี้แทบหายไปเพราะ stream ถูก multiplex
  • SSE เป็น text เท่านั้น. event เป็น UTF-8 text ถ้าจะส่ง binary ต้อง base64-encode ก่อน ซึ่งเปลืองไบต์เพิ่มราวหนึ่งในสาม WebSocket และ WebTransport พา binary ได้ในตัว
  • WebTransport datagram ไม่เชื่อถือได้โดยตั้งใจ. datagram อาจหายหรือมาถึงแบบสลับลำดับ และไม่มีการ retransmit เลย นั่นเป็น ฟีเจอร์ สำหรับ media แบบสด — เฟรมวิดีโอจากเมื่อ 200 ms ที่แล้วไร้ประโยชน์ ข้ามไปเลยดีกว่ารอ ถ้าคุณต้องการความเชื่อถือได้ ให้ใช้ WebTransport stream แทน
  • “Real-time” แทบไม่เคยแปลว่าสองทาง. ฟีเจอร์จำนวนน่าแปลกใจมีแต่การ push จาก server ไปยัง client สำหรับสิ่งเหล่านั้น SSE ขจัดความกังวลของ WebSocket ทั้งชุด — ไม่ต้อง reconnect เอง ไม่ต้อง heartbeat ปลอม ๆ เพื่อจำลองความมีชีวิต — แบบฟรี ๆ

ถ้าข้อมูลไหลจาก server ไปยัง client เท่านั้นและมี HTTP ธรรมดาให้ใช้ ให้คว้า SSE ก่อน คุณจะเขียน code น้อยลง ถ้า client ต้องส่งด้วย ให้ใช้ WebSocket — สุกงอมแล้ว รองรับทั่วทุกที่ และเป็นเส้นทางที่ส่วนที่เหลือของคอร์สนี้เตรียมคุณไว้แล้ว เก็บ long-polling ไว้ในกระเป๋าหลังเป็น fallback สำหรับเครือข่ายที่เป็นปฏิปักษ์ ส่วน WebTransport ก็จับตาไว้ระหว่างที่ยังสุกงอมขึ้นเรื่อย ๆ สำหรับงานเกมและ media ที่ datagram สำคัญ จับคู่ transport ให้เข้ากับ traffic ไม่ใช่เข้ากับกระแสฮือฮา

ใช้ WebSocket เมื่อ SSE เพียงพอ อาการ:

  • ต้องการเฉพาะ server push (notification, live feed) แต่เลือก WebSocket
  • complexity สูงกว่า SSE โดยไม่ได้ benefit
  • SSE ง่ายกว่า: auto-reconnect, native EventSource API, ทำงานบน HTTP/2

เลือก WebTransport เพราะ “ใหม่กว่า” อาการ:

  • WebTransport browser support ยังไม่ครบ (Safari ยังไม่รองรับ)
  • production app ที่ต้องการ wide support ยังไม่เหมาะ
  • ใช้ WebTransport เมื่อต้องการ UDP semantics: game ที่ latency สำคัญกว่า reliability

💡 ตัวอย่างจากของจริง

GitHub: ใช้ SSE สำหรับ live event stream — one-way push ที่ไม่ต้องการ bidirectional

Google Meet: ใช้ WebRTC (SRTP/DTLS) สำหรับ audio/video — UDP-based delivery ลด latency

Discord: ใช้ WebSocket — ต้องการ bidirectional (user action ↔ server event)

transport แบบใด stream event จาก server ไปยัง client เท่านั้นและ reconnect ให้อัตโนมัติในเบราว์เซอร์?
อะไรคือสิ่งที่ทำให้ WebTransport โดดเด่นเมื่อเทียบกับ WebSocket?
ทำไม WebTransport datagram บางครั้งจึงดีกว่า stream ที่เชื่อถือได้และเรียงลำดับ?