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 که به پروتکل دوطرفه و درخواست upgrade نیاز دارد، 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 در سال 2009 به عنوان بخشی از مشخصات HTML5 با نام 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 حافظه مصرف می‌کند که به یک سرور امکان می‌دهد با 1 GB RAM از 50,000+ اتصال همزمان پشتیبانی کند. این میزان به دلیل نبود پروتکل باینری به طور قابل توجهی کمتر از WebSocket است.

فرمت event-stream

فرمت text/event-stream — یک پروتکل متنی ساده است که در آن هر پیام از فیلدهای نام‌گذاری شده تشکیل شده که با کاراکترهای خط جدید از هم جدا می‌شوند. هر فیلد قالب «نام‌فیلد: مقدار» دارد. پیام‌ها با دو کاراکتر خط جدید ( ) از هم جدا می‌شوند.

فیلدهای پشتیبانی شده: event (نوع رویداد، پیش‌فرض message)، data (رشته داده، می‌تواند چندخطی باشد)، id (آخرین شناسه رویداد، در Last-Event-ID ذخیره می‌شود)، retry (زمان اتصال مجدد به میلی‌ثانیه). نظرات با دو نقطه (:) شروع می‌شوند و توسط تجزیه‌گر نادیده گرفته می‌شوند، اما می‌توانند برای heartbeat استفاده شوند.

فیلداجباریکاربرد
eventخیرنوع رویداد (پیش‌فرض message)
dataبلهرشته داده پیام
idخیرشناسه رویداد برای Last-Event-ID
retryخیرتأخیر اتصال مجدد به میلی‌ثانیه

نمونه جریان 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 (پیام بدون تعیین event دریافت شد)، 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 نیاز به درخواست upgrade از HTTP/1.1 به پروتکل WebSocket (ws://) دارد که ممکن است توسط پروکسی‌های شرکتی مسدود شود. SSE روی HTTP معمولی کار می‌کند، از هر پروکسی عبور می‌کند و نیازی به پیکربندی خاص سرور ندارد. SSE همچنین در پیاده‌سازی ساده‌تر است — سرور به کتابخانه اضافی نیاز ندارد، فقط کافی است پاسخ HTTP را به درستی شکل دهد.

طبق داده‌های تست‌های مقایسه‌ای (2024)، روی یک فرآیند سرور، SSE به دلیل پروتکل ساده‌تر، 30–50٪ اتصالات بیشتری نسبت به WebSocket پشتیبانی می‌کند. با این حال، latency SSE بالاتر است (50–200 ms در مقابل 10–50 ms برای WebSocket) زیرا SSE از HTTP chunked استفاده می‌کند، نه یک جریان دوطرفه کامل با فریم‌های باینری.

ویژگی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: {"زمان": "${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)، مصرف باتری در iOS با SSE 40٪ کمتر از اتصال دائمی WebSocket است، به دلیل نبود بسته‌های 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 از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید