SSE (Server-Sent Events) — استاندارد W3C است که به سرور امکان میدهد دادههای جریانی را از طریق یک اتصال HTTP به صورت یکطرفه به کلاینت ارسال کند. برخلاف WebSocket، SSE روی HTTP معمولی کار میکند و به پروتکل یا کتابخانه خاصی در سمت کلاینت نیاز ندارد. طبق مشخصات W3C HTML Living Standard (2025)، EventSource API در تمام مرورگرهای مدرن از جمله Chrome، Firefox، Safari و Edge پشتیبانی میشود.
نکات کلیدی
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 به این صورت است: کلاینت یک نمونه 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 است.
فرمت text/event-stream — یک پروتکل متنی ساده است که در آن هر پیام از فیلدهای نامگذاری شده تشکیل شده که با کاراکترهای خط جدید از هم جدا میشوند. هر فیلد قالب «نامفیلد: مقدار» دارد. پیامها با دو کاراکتر خط جدید ( ) از هم جدا میشوند.
فیلدهای پشتیبانی شده: event (نوع رویداد، پیشفرض message)، data (رشته داده، میتواند چندخطی باشد)، id (آخرین شناسه رویداد، در Last-Event-ID ذخیره میشود)، retry (زمان اتصال مجدد به میلیثانیه). نظرات با دو نقطه (:) شروع میشوند و توسط تجزیهگر نادیده گرفته میشوند، اما میتوانند برای heartbeat استفاده شوند.
| فیلد | اجباری | کاربرد |
|---|---|---|
| event | خیر | نوع رویداد (پیشفرض message) |
| data | بله | رشته داده پیام |
| id | خیر | شناسه رویداد برای Last-Event-ID |
| retry | خیر | تأخیر اتصال مجدد به میلیثانیه |
: 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 — رابط داخلی مرورگر برای دریافت 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.
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 — فناوریهای مختلف برای ارتباط بلادرنگ هستند که هر کدام نقاط قوت خود را دارند. 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 استفاده میکند، نه یک جریان دوطرفه کامل با فریمهای باینری.
| ویژگی | SSE | WebSocket |
|---|---|---|
| جهت | سرور → کلاینت | دوطرفه |
| پروتکل | HTTP (text/event-stream) | ws:// / wss:// (RFC 6455) |
| مرورگرها | 97.5٪ (EventSource داخلی) | 97٪ (WebSocket داخلی) |
| دادهها | فقط متن / JSON | متن + باینری (Blob, ArrayBuffer) |
| عبور از پروکسی | از همه پروکسیها عبور میکند | نیاز به تنظیمات پروکسی |
| اتصال مجدد | خودکار (مرورگر) | پیادهسازی دستی |
| تاریخچه | Last-Event-ID | بدون تاریخچه داخلی |
پیادهسازی 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 به صراحت به مرورگر میگوید اتصال را باز نگه دارد.
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);
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 در برنامههای موبایل به دلیل نبود پیادهسازی بومی 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 — انتقال یکطرفه (سرور → کلاینت) از طریق HTTP، بدون نیاز به کتابخانه در سمت کلاینت. WebSocket — انتقال دوطرفه با پروتکل باینری. SSE در پیادهسازی سادهتر است، WebSocket برای کارهایی مناسب است که کلاینت نیز داده ارسال میکند.
خیر، SSE فقط دادههای متنی را منتقل میکند. برای دادههای باینری (تصاویر، صدا) کدگذاری Base64 مورد نیاز است که اندازه را 33٪ افزایش میدهد. برای جریانهای باینری بهتر است از WebSocket استفاده کنید.
EventSource به طور خودکار پس از قطعی دوباره متصل میشود. زمان تأخیر توسط فیلد retry در جریان تعیین میشود (پیشفرض 1000 ms). هنگام اتصال مجدد، مرورگر هدر Last-Event-ID را ارسال میکند که به سرور امکان میدهد جریان را از نقطه قطع شده بازیابی کند.
هر مرورگر محدودیتی برای تعداد اتصالات همزمان HTTP با یک دامنه دارد. برای HTTP/1.1 — 6–8 اتصال به ازای هر دامنه، برای HTTP/2 — تا 100. SSE از یک اتصال استفاده میکند، بنابراین رقابتی با سایر درخواستها ایجاد نمیشود.
SSE فقط برای دریافت پیامها (ورودی) مناسب است. برای ارسال پیامها (خروجی) به یک درخواست HTTP جداگانه (POST) نیاز است. برای چت کامل بهتر است از WebSocket یا Socket.IO با ارتباط دوطرفه در یک اتصال استفاده کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید