SSE — คืออะไร, Server-Sent Events และการสตรีมทางเดียว

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-02 เวลาอ่าน: 8 นาที

SSE (Server-Sent Events) เป็นมาตรฐาน W3C ที่ช่วยให้เซิร์ฟเวอร์สามารถส่งข้อมูลสตรีมไปยังไคลเอนต์ผ่านการเชื่อมต่อ HTTP เดียวในโหมดทางเดียวได้ แตกต่างจาก WebSocket, SSE ทำงานบน HTTP ทั่วไปและไม่ต้องการโปรโตคอลพิเศษหรือไลบรารีทางฝั่งไคลเอนต์ ตาม ข้อกำหนด W3C HTML Living Standard (2025), EventSource API รองรับในทุก เบราว์เซอร์ที่ทันสมัย รวมถึง Chrome, Firefox, Safari และ Edge

โดยสรุป

  • SSE เป็นมาตรฐานสำหรับการส่งข้อมูลทางเดียวจากเซิร์ฟเวอร์ไปยังไคลเอนต์ผ่านการเชื่อมต่อ HTTP
  • EventSource API เป็นอินเทอร์เฟสของเบราว์เซอร์ในตัวสำหรับรับ SSE โดยไม่ต้องใช้ไลบรารีภายนอก
  • เชื่อมต่อใหม่อัตโนมัติ — เบราว์เซอร์จะเชื่อมต่อใหม่โดยอัตโนมัติเมื่อการเชื่อมต่อขาดหาย
  • โปรโตคอลข้อความ — ข้อมูลถูกส่งในรูปแบบ text/event-stream ด้วยรูปแบบข้อความที่ง่าย
  • การสื่อสารทางเดียว — SSE เหมาะสำหรับการแจ้งเตือน, ฟีดข่าว, ตัวเลขและมอนิเตอร์ แต่ไม่ใช่สำหรับแชท

SSE คืออะไร?

SSE (Server-Sent Events) เป็นเทคโนโลยีที่ช่วยให้เว็บเซิร์ฟเวอร์สามารถส่งข้อมูลไปยังไคลเอนต์ได้ตลอดเวลาหลังจากสร้างการเชื่อมต่อ มันได้รับการมาตรฐานโดย WHATWG เป็นส่วนหนึ่งของ HTML Living Standard และใช้ MIME ชนิด text/event-stream SSE รองรับการส่งข้อมูลข้อความโดยสามารถระบุตัวระบุข้อความ, ชนิดของเหตุการณ์ และเวลาหน่วงในการเชื่อมต่อใหม่

แตกต่างจาก WebSocket ที่ต้องการ โปรโตคอลสองทาง และคำขออัปเกรด, SSE ทำงานบน HTTP ทั่วไป เซิร์ฟเวอร์จะตั้งค่าส่วนหัว Content-Type: text/event-stream, ส่งข้อมูลเป็นส่วนๆ และเก็บการเชื่อมต่อไว้ ไคลเอนต์จะรับข้อมูลผ่าน EventSource API ของเบราว์เซอร์, ซึ่งจะวิเคราะห์สตรีมโดยอัตโนมัติและสร้างเหตุการณ์

ตาม CanIUse (2025), EventSource API รองรับใน 97.5% ของเบราว์เซอร์ทั่วโลก ไม่รองรับใน Internet Explorer และเบราว์เซอร์มือถือบางตัว (Samsung Internet ก่อนรุ่น 7.0) สำหรับกรณีเหล่านี้, มีโพลีฟิลที่จำลอง EventSource ผ่าน XHR streaming SSE ไม่ทำงานกับ HTTP/1.1 pipelining แต่เข้ากันได้อย่างสมบูรณ์กับ HTTP/2 server push

ประวัติศาสตร์และการมาตรฐาน

SSE ถูกเสนอเป็นส่วนหนึ่งของข้อกำหนด HTML5 ในปี 2009 ภายใต้ชื่อ Server-Sent DOM Events การนำไปใช้ครั้งแรกปรากฏใน Opera 9.0, จากนั้น Firefox 6.0 (2011), Chrome 9.0 (2011) และ Safari 5.0 (2010) ในปี 2015, ข้อกำหนดได้ถูกย้ายไปยังส่วนแยกของ HTML Living Standard แม้จะมีประวัติศาสตร์กว่าสิบปี, SSE ก็ยังไม่เป็นที่นิยมเท่า WebSocket เนื่องจากลักษณะทางเดียวของมัน

SSE ทำงานอย่างไร

กลไกการทำงานของ SSE มีดังนี้: ไคลเอนต์สร้างอินสแตนซ์ EventSource ด้วย URL ของจุดสิ้นสุดของเซิร์ฟเวอร์ เบราว์เซอร์จะส่งคำขอ GET ด้วยส่วนหัว Accept: text/event-stream เซิร์ฟเวอร์จะตอบกลับด้วยสถานะ 200 OK และส่วนหัว Content-Type: text/event-stream, จากนั้นเริ่มส่งข้อมูลในรูปแบบ event-stream การเชื่อมต่อจะเปิดอยู่จนกว่าเซิร์ฟเวอร์จะส่งสัญญาณสิ้นสุดหรือไคลเอนต์เรียก close()

ฝั่งเซิร์ฟเวอร์, ข้อมูลจะถูกส่งเป็นส่วนๆ (chunked transfer encoding) แต่ละส่วนข้อมูลคือข้อความที่ประกอบด้วยบรรทัดของฟิลด์ (event, data, id, retry) เซิร์ฟเวอร์สามารถส่งข้อความได้ตลอดเวลา, ทำให้ SSE เหมาะสำหรับการแจ้งเตือนและการอัปเดตสถานะ การเชื่อมต่อไม่ต้องการการแลกเปลี่ยนแพ็กเก็ต heartbeat อย่างต่อเนื่อง (เช่น WebSocket), แม้ว่าฟิลด์ retry จะควบคุมความถี่ในการเชื่อมต่อใหม่

ตาม การทดสอบประสิทธิภาพ (2024), SSE ให้ปริมาณงานสูงถึง 10,000 ข้อความต่อวินาทีต่อการเชื่อมต่อ โดยมีขนาดข้อความ 256 ไบต์ ฝั่งเซิร์ฟเวอร์, แต่ละการเชื่อมต่อ SSE ใช้หน่วยความจำประมาณ 5–10 KB, ทำให้เซิร์ฟเวอร์หนึ่งตัวสามารถรองรับการเชื่อมต่อพร้อมกันมากกว่า 50,000 รายการด้วย 1 GB RAM ซึ่งน้อยกว่า WebSocket มากเนื่องจากไม่มีโปรโตคอลไบนารี

รูปแบบ event-stream

รูปแบบ text/event-stream เป็นโปรโตคอลข้อความที่ง่าย โดยแต่ละข้อความประกอบด้วยฟิลด์ที่มีชื่อซึ่งคั่นด้วยอักขระขึ้นบรรทัดใหม่ แต่ละฟิลด์มีรูปแบบ “ชื่อฟิลด์: ค่า” ข้อความจะถูกคั่นด้วยอักขระขึ้นบรรทัดใหม่สองตัว (\n\n)

ฟิลด์ที่รองรับ: event (ชนิดของเหตุการณ์, ค่าเริ่มต้นคือ message), data (สตริงข้อมูล, สามารถมีหลายบรรทัดได้), id (ตัวระบุเหตุการณ์ล่าสุด, เก็บไว้ใน Last-Event-ID), retry (เวลาหน่วงในการเชื่อมต่อใหม่ในหน่วยมิลลิวินาที) ความคิดเห็นเริ่มต้นด้วยเครื่องหมายจุลภาค (:) และถูกละเว้นโดยตัวแยกวิเคราะห์ แต่สามารถใช้สำหรับ heartbeat ได้

ฟิลด์จำเป็นวัตถุประสงค์
eventไม่ชนิดของเหตุการณ์ (ค่าเริ่มต้นคือ message)
dataใช่สตริงข้อมูลของข้อความ
idไม่ตัวระบุเหตุการณ์สำหรับ Last-Event-ID
retryไม่เวลาหน่วงในการเชื่อมต่อใหม่ในหน่วย ms

ตัวอย่าง event-stream

text
: heartbeat comment
event: update
data: {"user": "Alice", "action": "typing"}
id: 1001

event: notification
data: {"type": "info", "text": "New version available"}
data: {"type": "action", "url": "/upgrade"}
retry: 3000

event: close
data: Session ended

EventSource API ฝั่งไคลเอนต์

EventSource API เป็นอินเทอร์เฟสของเบราว์เซอร์ในตัวสำหรับรับ SSE เพื่อสร้างการเชื่อมต่อ, เพียงเรียกคอนสตรักเตอร์ด้วย URL ของจุดสิ้นสุด EventSource จะสร้างการเชื่อมต่อโดยอัตโนมัติ, จัดการการเชื่อมต่อใหม่ และแยกวิเคราะห์ข้อความขาเข้าเป็นเหตุการณ์ JavaScript

เหตุการณ์ของ EventSource: open (การเชื่อมต่อถูกสร้าง), message (ได้รับข้อความโดยไม่ระบุเหตุการณ์), error (ข้อผิดพลาดของการเชื่อมต่อ) สำหรับเหตุการณ์ที่กำหนดเอง (event: custom), คุณสามารถใช้ addEventListener กับชื่อของเหตุการณ์ได้ EventSource จะส่งส่วนหัว Last-Event-ID โดยอัตโนมัติเมื่อเชื่อมต่อใหม่, ทำให้เซิร์ฟเวอร์สามารถเริ่มสตรีมใหม่จากจุดที่ถูกขัดจังหวะได้

ตาม เอกสาร MDN (2025), EventSource รองรับ CORS และการส่งข้อมูลรับรองความถูกต้อง (withCredentials) EventSource ไม่เหมาะสำหรับการส่งส่วนหัวที่กำหนดเองหรือเนื้อความของคำขอ — จำเป็นต้องใช้การนำไปใช้แบบเองโดยใช้ fetch + ReadableStream EventSource ไม่รองรับข้อมูลไบนารี — เฉพาะข้อความและ JSON

โค้ด JavaScript ฝั่งไคลเอนต์

js
const eventSource = new EventSource('/api/events/stream');

eventSource.addEventListener('open', () => {
    console.log('เปิดการเชื่อมต่อ SSE แล้ว');
});

eventSource.addEventListener('message', (event) => {
    const data = JSON.parse(event.data);
    console.log('ได้รับ:', data);
    renderUpdate(data);
});

eventSource.addEventListener('notification', (event) => {
    const notification = JSON.parse(event.data);
    showNotification(notification.text);
});

eventSource.addEventListener('error', (error) => {
    console.error('ข้อผิดพลาด SSE:', error);
    // เบราว์เซอร์เชื่อมต่อใหม่อัตโนมัติ
});

// ปิดการเชื่อมต่อ
eventSource.close();

SSE เทียบ WebSocket: เปรียบเทียบ

SSE และ WebSocket เป็นเทคโนโลยีที่แตกต่างกันสำหรับการสื่อสารแบบเรียลไทม์, แต่ละแบบมีจุดแข็งของตัวเอง WebSocket เหมาะสำหรับการแลกเปลี่ยนข้อมูลสองทาง (แชท, เกม, การแก้ไขร่วมกัน), ในขณะที่ SSE สำหรับสตรีมทางเดียวจากเซิร์ฟเวอร์ไปยังไคลเอนต์ (การแจ้งเตือน, ฟีดข่าว, ตัวเลข)

ความแตกต่างหลัก คือ WebSocket ต้องการคำขออัปเกรดจาก HTTP/1.1 ไปยังโปรโตคอล WebSocket (ws://), ซึ่งอาจถูกบล็อกโดยพร็อกซีขององค์กร SSE ทำงานบน HTTP ทั่วไป, ผ่านพร็อกซีใดๆ ก็ได้ และไม่ต้องการการกำหนดค่าเซิร์ฟเวอร์พิเศษ SSE ยังนำไปใช้ได้ง่ายกว่า — เซิร์ฟเวอร์ไม่ต้องการไลบรารีเพิ่มเติม, แค่จัดรูปแบบการตอบกลับ HTTP ให้ถูกต้อง

ตาม การทดสอบเปรียบเทียบ (2024), บนกระบวนการเซิร์ฟเวอร์เดียว SSE รองรับการเชื่อมต่อมากกว่า WebSocket 30–50% เนื่องจากโปรโตคอลที่ง่ายกว่า อย่างไรก็ตาม, SSE มีเวลาแฝงสูงกว่า (50–200 ms เทียบกับ 10–50 ms ของ WebSocket) เนื่องจาก SSE ใช้ HTTP แบบเป็นส่วนๆ แทนที่จะเป็นสตรีมสองทางที่สมบูรณ์ด้วยเฟรมไบนารี

ลักษณะSSEWebSocket
ทิศทางเซิร์ฟเวอร์ → ไคลเอนต์สองทาง
โปรโตคอลHTTP (text/event-stream)ws:// / wss:// (RFC 6455)
เบราว์เซอร์97.5% (EventSource ในตัว)97% (WebSocket ในตัว)
ข้อมูลเฉพาะข้อความ / JSONข้อความ + ไบนารี (Blob, ArrayBuffer)
การจัดการพร็อกซีผ่านพร็อกซีใดก็ได้ต้องการการตั้งค่าพร็อกซี
การเชื่อมต่อใหม่อัตโนมัติ (เบราว์เซอร์)การนำไปใช้ด้วยตนเอง
ประวัติLast-Event-IDไม่มีประวัติในตัว

วิธีนำ SSE ไปใช้บนเซิร์ฟเวอร์

การนำ SSE ไปใช้บนเซิร์ฟเวอร์ ไม่ต้องการไลบรารี — แค่ตั้งค่าส่วนหัว HTTP ที่ถูกต้องและส่งข้อมูลในรูปแบบ text/event-stream มาดูตัวอย่างใน Node.js โดยใช้โมดูล http ในตัว เซิร์ฟเวอร์จะตั้งค่าส่วนหัว Content-Type และ Cache-Control, จากนั้นส่งข้อความทุก N วินาที

ตาม MDN Web Docs (2025), ส่วนหัวที่จำเป็นสำหรับ SSE คือ: Content-Type: text/event-stream, Cache-Control: no-cache และ Connection: keep-alive หากไม่มี Cache-Control, เบราว์เซอร์อาจแคชสตรีม SSE, ซึ่งจะหยุดการจัดส่ง Connection: keep-alive จะบอกเบราว์เซอร์อย่างชัดแจ้งให้เก็บการเชื่อมต่อไว้

โค้ดเซิร์ฟเวอร์ใน Node.js

js
const http = require('http');

http.createServer((req, res) => {
    res.writeHead(200, {
        'Content-Type': 'text/event-stream',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive'
    });

    let eventId = 0;
    const interval = setInterval(() => {
        eventId++;
        res.write(`id: ${eventId}\n`);
        res.write(`event: update\n`);
        res.write(`data: {"time": "${new Date().toISOString()}", "id":${eventId}}\n\n`);
    }, 2000);

    req.on('close', () => {
        clearInterval(interval);
    });
}).listen(3000);

SSE ใน Python (Flask)

python
from flask import Response, Flask
import time
import json

app = Flask(__name__)

@app.route('/stream')
def stream():
    def generate():
        event_id = 0
        while True:
            event_id += 1
            data = json.dumps(
                {'ticker': 'AAPL', 'price': 150.25})
            yield f'id: {event_id}\nevent: price\ndata: {data}\n\n'
            time.sleep(1)
    return Response(generate(),
        mimetype='text/event-stream')

SSE ในแอพมือถือ

การใช้ SSE ในแอพมือถือ ถูกจำกัดโดยการขาดการนำไปใช้ EventSource ดั้งเดิมสำหรับ iOS และ Android บนแพลตฟอร์มมือถือ, SSE ถูกนำไปใช้ผ่านไลบรารีของบุคคลที่สาม: บน iOS — ผ่าน URLSession กับ NSURLProtocol, บน Android — ผ่าน OkHttp กับการรองรับ SSE (okhttp-sse) สำหรับ React Native และ Flutter, มีแพ็กเกจที่จำลอง EventSource

บน iOS, การนำไปใช้ SSE ดั้งเดิมเป็นไปได้ผ่าน URLSessionDataDelegate เมื่อรับข้อมูลในเมธอด urlSession(_:dataTask:didReceive:), แอพจะสะสมบัฟเฟอร์และแยกวิเคราะห์รูปแบบ event-stream ด้วยตนเอง ตาม บล็อกการพัฒนา iOS (2024), การใช้แบตเตอรี่กับ SSE บน iOS ต่ำกว่าการเชื่อมต่อ WebSocket คงที่ 40% เนื่องจากไม่มีแพ็กเก็ต heartbeat

บน Android, OkHttp ให้คลาส EventSource.Factory สำหรับสมัครรับสตรีม SSE แอพ Android สามารถใช้ SSE สำหรับการแจ้งเตือนเมื่อ FCM ไม่พร้อมใช้งาน หรือสำหรับการซิงค์ข้อมูลในพื้นหลัง SSE บน Android ทำงานได้ดีกับ WorkManager สำหรับงานพื้นหลังที่มีอายุยืนยาว ตาม เอกสาร OkHttp (2025), okhttp-sse รองรับการเชื่อมต่อใหม่อัตโนมัติด้วย listener ที่กำหนดเอง

คำถามที่พบบ่อย

SSE แตกต่างจาก WebSocket อย่างไร?

SSE คือการส่งทางเดียว (เซิร์ฟเวอร์ → ไคลเอนต์) บน HTTP, ไม่ต้องการไลบรารีบนไคลเอนต์ WebSocket คือการส่งสองทางด้วยโปรโตคอลไบนารี SSE นำไปใช้ได้ง่ายกว่า, WebSocket เหมาะสำหรับงานที่ไคลเอนต์ก็ส่งข้อมูลเช่นกัน

SSE รองรับข้อมูลไบนารีหรือไม่?

ไม่, SSE ส่งเฉพาะ ข้อมูลข้อความ สำหรับข้อมูลไบนารี (รูปภาพ, เสียง), จำเป็นต้องใช้การเข้ารหัส Base64, ซึ่งเพิ่มขนาดขึ้น 33% สำหรับสตรีมไบนารี, ควรใช้ WebSocket

SSE จัดการการขาดของการเชื่อมต่ออย่างไร?

EventSource จะเชื่อมต่อใหม่โดยอัตโนมัติเมื่อเกิดการขาดการเชื่อมต่อ เวลาหน่วงถูกกำหนดโดยฟิลด์ retry ในสตรีม (ค่าเริ่มต้น 1000 ms) เมื่อเชื่อมต่อใหม่, เบราว์เซอร์จะส่งส่วนหัว Last-Event-ID, ทำให้เซิร์ฟเวอร์สามารถเริ่มสตรีมใหม่จากจุดที่ถูกขัดจังหวะได้

เบราว์เซอร์หนึ่งสามารถเก็บการเชื่อมต่อ SSE ได้กี่ครั้ง?

แต่ละเบราว์เซอร์มีขีดจำกัดของจำนวนการเชื่อมต่อ HTTP พร้อมกันกับโดเมนเดียว สำหรับ HTTP/1.1 — 6–8 การเชื่อมต่อ ต่อโดเมน, สำหรับ HTTP/2 — ถึง 100 ครั้ง SSE ใช้การเชื่อมต่อเดียว, ดังนั้นจึงไม่มีการแข่งขันกับคำขออื่นๆ

สามารถใช้ SSE สำหรับแชทได้หรือไม่?

SSE เหมาะ เฉพาะสำหรับการรับข้อความ (ขาเข้า) สำหรับการส่งข้อความ (ขาออก), จำเป็นต้องมีคำขอ HTTP แยก (POST) สำหรับแชทที่สมบูรณ์, สะดวกกว่าในการใช้ WebSocket หรือ Socket.IO กับการสื่อสารสองทางในการเชื่อมต่อเดียว

สรุป

  • SSE เป็นมาตรฐานสำหรับการส่งข้อมูลทางเดียวจากเซิร์ฟเวอร์ไปยังไคลเอนต์ผ่านการเชื่อมต่อ HTTP ทั่วไปโดยไม่ต้องใช้ไลบรารีเพิ่มเติม
  • EventSource API เป็นอินเทอร์เฟสเบราว์เซอร์ในตัวที่รองรับโดย 97.5% ของเบราว์เซอร์ที่ทันสมัย
  • โปรโตคอลข้อความที่ง่าย text/event-stream พร้อมฟิลด์ event, data, id และ retry
  • การเชื่อมต่อใหม่อัตโนมัติ พร้อมการรองรับ Last-Event-ID เพื่อเริ่มสตรีมใหม่จากจุดที่ถูกขัดจังหวะ
  • ประสิทธิภาพ — SSE รองรับการเชื่อมต่อเซิร์ฟเวอร์มากกว่า (50,000+) เมื่อเทียบกับ WebSocket เนื่องจากโปรโตคอลที่ง่ายกว่า
  • บนแพลตฟอร์มมือถือ SSE ถูกนำไปใช้ผ่าน OkHttp (Android) หรือ URLSession (iOS) พร้อมการแยกวิเคราะห์สตรีมด้วยตนเอง
  • สำหรับสตรีมทางเดียว (การแจ้งเตือน, ฟีด, ตัวเลข) เลือก SSE, สำหรับการสื่อสารสองทาง — WebSocket หรือ Socket.IO

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม