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 للمتصفح، والتي تقوم تلقائيًا بتحليل الدفق وإنشاء الأحداث.

وفقًا لCanIUse (2025)، فإن واجهة EventSource API مدعومة في 97.5% من المتصفحات عالميًا. وهي غير مدعومة في Internet Explorer وبعض متصفحات الجوال (Samsung Internet قبل الإصدار 7.0). ولهذه الحالات، توجد polyfills تقوم بمحاكاة 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 كبايت من الذاكرة، مما يسمح لخادم واحد بدعم أكثر من 50 000 اتصال متزامن مع 1 جيجابايت من 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لاتأخير إعادة الاتصال بالملي ثانية

مثال على 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 عددًا أكبر بنسبة 30–50% من الاتصالات مقارنة بـ WebSocket بسبب البروتوكول الأبسط. ولكن لدى SSE زمن استجابة أعلى (50–200 ملي ثانية مقابل 10–50 ملي ثانية لـ 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 أقل بنسبة 40% مقارنة باتصال WebSocket المستمر بسبب عدم وجود حزم heartbeat.

على Android، يوفر OkHttp الفئة EventSource.Factory للاشتراك في تدفقات SSE. يمكن لتطبيقات Android استخدام SSE للإشعارات عندما يكون FCM غير متاح، أو لمزامنة البيانات في الخلفية. يعمل SSE على Android بشكل جيد مع WorkManager للمهام الخلفية طويلة العمر. وفقًا لوثائق OkHttp (2025)، يدعم okhttp-sse إعادة الاتصال تلقائيًا مع مستمع مخصص.

الأسئلة الشائعة

ما الفرق بين SSE و WebSocket؟

SSE — نقل أحادي الاتجاه (خادم → عميل) عبر HTTP، لا يتطلب مكتبات على العميل. WebSocket — نقل ثنائي الاتجاه مع بروتوكول ثنائي. SSE أبسط في التنفيذ، WebSocket مناسب للمهام حيث يرسل العميل البيانات أيضًا.

هل يدعم SSE البيانات الثنائية؟

لا، SSE ينقل فقط البيانات النصية. للبيانات الثنائية (الصور، الصوت)، يلزم تشفير Base64، والذي يزيد الحجم بنسبة 33%. للتدفقات الثنائية، من الأفضل استخدام WebSocket.

كيف يتعامل SSE مع انقطاع الاتصال؟

EventSource يعيد الاتصال تلقائيًا عند حدوث انقطاع. يتم تعيين وقت التأخير عبر حقل retry في الدفق (افتراضيًا 1000 ملي ثانية). عند إعادة الاتصال، يرسل المتصفح ترويسة 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. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا