การออกแบบ Server
จนถึงตอนนี้คอร์สนี้อยู่ฝั่ง client เป็นหลัก — เปิด socket, ส่ง frame, เฝ้าดูข้อความวิ่งเข้ามา โมดูลนี้จะหันกล้องกลับด้าน WebSocket server คือ process ที่รันค้างไว้นาน คอย holding connection ที่เปิดอยู่ จำนวนมาก พร้อมกัน และตัดสินใจว่าใครจะได้ยินอะไร นั่นเป็น mental model ที่ต่างจาก HTTP handler อย่างแท้จริง และการทำให้ถูกต้องคือเส้นแบ่งระหว่างเดโมกับระบบจริง
WebSocket server ทำอะไรกันแน่
หัวข้อที่มีชื่อว่า “WebSocket server ทำอะไรกันแน่”HTTP server คิดในแง่หนึ่ง request หนึ่ง response แล้วก็ลืมคุณไป WebSocket server ลืมคุณไม่ได้ — คุณยังอยู่บนสายอยู่ ถ้าถอดงานลงมาถึงแก่น จะเหลือความรับผิดชอบจริง ๆ อยู่สี่อย่าง:
- รับ upgrade (Accept upgrades). connection เริ่มต้นชีวิตในฐานะ HTTP request ธรรมดาที่พก header
Upgrade: websocketมาด้วย server ตรวจสอบความถูกต้องแล้วสลับ socket ไปใช้ protocol WebSocket จากจุดนั้นเป็นต้นไปก็กลายเป็นท่อถาวร ไม่ใช่ request อีกต่อไป - ติดตาม connection (Track connections). ทุก socket ที่รับเข้ามาต้องถูกจดจำ server เก็บชุดของผู้ที่เชื่อมต่ออยู่แบบ live ไว้เพื่อให้หากลับมาได้ในภายหลัง — เพื่อ push update, เพื่อนับจำนวน, หรือเพื่อ clean up เมื่อพวกเขาจากไป
- Route message (Route messages). พอ frame เข้ามา server อ่านแล้วตัดสินว่าหมายถึงอะไร: บรรทัดแชทของ room หนึ่ง, request subscribe, ping หรือคำสั่ง การ routing เปลี่ยน byte ดิบให้กลายเป็นพฤติกรรมของ application
- Broadcast. ลูกเล่นเด่น เพราะ server ถือ socket ที่เปิดอยู่ไว้ทุกตัว จึงส่ง event เดียวไปยัง client จำนวนมาก ได้พร้อมกัน — ในวินาทีที่เกิดขึ้นจริง โดยไม่ต้องมีใครร้องขอ
สังเกตว่าสามในสี่อย่างนี้เป็นสิ่งที่ HTTP server ธรรมดาไม่เคยต้องทำ การ tracking, การ routing บน connection ที่ถาวร และการ fan-out จะมีความหมายก็ต่อเมื่อ connection ยังเปิดค้างอยู่
หนึ่ง server, หลาย client
หัวข้อที่มีชื่อว่า “หนึ่ง server, หลาย client”วิธีที่ดีในการมองภาพ WebSocket server คือมองเป็น hub ที่ถือสายหนึ่งเส้นไปยังแต่ละ client ข้อความจาก client เดี่ยว ๆ คนใดก็ตามสามารถเข้ามา ถูกประมวลผล แล้วก็ส่งกลับออกไปยัง client หนึ่งราย, กลุ่มย่อย, หรือทุกคน:
flowchart TB
subgraph clients["Connected clients"]
A["client A"]
B["client B"]
C["client C"]
D["client D"]
end
S["WebSocket server<br/>(tracks every open socket)"]
A <--> S
B <--> S
C <--> S
D <--> S
A -. "sends one message" .-> S
S == "broadcast to all" ==> B
S == "broadcast to all" ==> C
S == "broadcast to all" ==> D เส้นที่มีหัวลูกศรสองด้านคือ connection ถาวร ส่วนเส้นหนาคือข้อความขาเข้าหนึ่งข้อความที่ถูก fan-out ออกไปยังคนอื่นทุกคน จำรูปทรงนี้ไว้ให้ดี — เกือบทุกอย่างในโมดูลนี้คือการขัดเกลารูปทรงนี้
โมดูลนี้ครอบคลุมอะไร
หัวข้อที่มีชื่อว่า “โมดูลนี้ครอบคลุมอะไร”โมดูลนี้ — การออกแบบ Server — สร้างความรู้ WebSocket ฝั่ง server ครึ่งหนึ่งของคุณ ทีละชั้น:
- การออกแบบ Server (คุณอยู่ที่นี่) — งานสี่อย่างของ server และ
wsserver ตัวแรกที่รันได้จริง - A WebSocket server — ไลบรารี
ws:WebSocketServer,connectionevent,ws.on('message'), และws.send - Connection state — การแนบข้อมูลต่อ socket (user id, subscriptions) แล้ว clean up ตอน close
- Rooms and broadcast — การจัดกลุ่ม client เข้าเป็น channel และ fan ข้อความออกไปยัง room หนึ่งเทียบกับทุกคน
- Backpressure — เกิดอะไรขึ้นเมื่อ client ช้าตามไม่ทัน และจะปกป้อง memory ของ server อย่างไร
server ที่รันได้จริงตัวแรก
หัวข้อที่มีชื่อว่า “server ที่รันได้จริงตัวแรก”เดโมในโมดูลนี้คือ Node server จริง ที่สร้างบนไลบรารี ws — ไลบรารี WebSocket ที่ใช้กันแพร่หลายที่สุดสำหรับ Node เปิดอันใดก็ได้ใน StackBlitz เพื่อรัน WebSocketServer ของจริง จากนั้น npm run client ใน terminal ที่สองเพื่อเชื่อมต่อ
ตลอดทั้งโมดูลนี้ code ที่คุณเห็นคือ body ของ connection handler — รันหนึ่งครั้งต่อ client ที่เชื่อมต่อเข้ามา โดยมีสาม identifier อยู่ใน scope แล้ว: ws (socket ของ client รายนี้), wss (server, ใช้สำหรับ broadcast), และ req (upgrade request) ตัวอย่างด้านล่างทักทาย client ใหม่แต่ละราย, echo สิ่งที่พวกเขาส่งมา, และ log เมื่อพวกเขาจากไป
Needs the Node.js runtime — open in StackBlitz to run.
เมื่อคุณเชื่อมต่อ client เข้ามา server จะส่งคำทักทายทันที จากนั้น echo message ของคุณกลับมาพร้อม prefix echo: การ ws.send ตอน connect — ก่อนที่ client จะพูดอะไรเลย — คือสิ่งที่ HTTP ไม่มีวันทำได้: server พูดก่อน ทุกอย่างที่เหลือในโมดูลนี้ต่อยอดจากการถือ connection นั้นเปิดค้างไว้แล้วตัดสินใจว่าจะส่งอะไรผ่านเข้าไป