Long Polling مقابل WebSocket في Java: أيهما تختار للوقت الفعلي؟

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Long Polling مقابل WebSocket في Java: مبارزة تقنيات الوقت الفعلي

\n\n

تخيل: أنت تطور دردشة، أو محطة تداول، أو لعبة عبر الإنترنت بلغة Java. المستخدم ينتظر التحديثات، والخادم صامت. كيف تجعل البيانات تصل فورًا؟ في السابق، كان هناك حل واحد فقط — Long Polling. اليوم، على الساحة WebSocket. لكن من سينتصر في المعركة الحقيقية؟

\n\n

في هذه المقالة، لن نقارن المفاهيم فقط. سنكتب كودًا حيًا بلغة Java، ونلقي نظرة على داخل كلتا التقنيتين، ونقرر ما الذي سنستخدمه في مشروعك القادم. مرحبًا بكم في الحلبة!

\n\n

ما هو Long Polling (ولماذا ليس مجرد "استقصاء")؟

\n\n

HTTP التقليدي يشبه الرسالة: ترسل طلبًا → تحصل على رد. إذا لم يكن لدى الخادم ما يقوله، فإنه يعيد ردًا فارغًا. يضطر العميل إلى السؤال مرة أخرى كل N ثانية. هذا هو Short Polling — طريق مسدود.

\n\n

Long Polling يعمل بذكاء أكبر. يرسل العميل طلبًا، والخادم... ينام. يبقي الاتصال مفتوحًا حتى يظهر حدث جديد (أو حتى انتهاء المهلة). بمجرد حدوث الحدث، يستيقظ الخادم ويرسل الرد. يقوم العميل فورًا بإنشاء طلب Long Polling جديد. تتكرر الدورة.

\n\n

Long Polling بلغة Java: تنفيذ بسيط

\n\n

لنتخيل أننا نكتب خادم إشعارات باستخدام Servlet API الخالص (بدون Spring، لتوضيح الفكرة). بالنسبة لـ Long Polling، سنحتاج إلى معالجة غير متزامنة (AsyncContext)، وإلا فإن الخادم سيعطل جميع الخيوط.

\n\n
import javax.servlet.AsyncContext;\nimport javax.servlet.annotation.WebServlet;\nimport javax.servlet.http.HttpServlet;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.Queue;\nimport java.util.concurrent.ConcurrentLinkedQueue;\n\n@WebServlet(urlPatterns = "/long-poll", asyncSupported = true)\npublic class LongPollingServlet extends HttpServlet {\n\n    // قائمة لتخزين الاتصالات "النائمة"\n    private static final Queue<AsyncContext> WAITING_CLIENTS = new ConcurrentLinkedQueue<>();\n\n    @Override\n    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {\n        AsyncContext asyncContext = req.startAsync();\n        asyncContext.setTimeout(30_000); // مهلة 30 ثانية\n\n        // حفظ السياق\n        WAITING_CLIENTS.add(asyncContext);\n\n        // إذا انتهت المهلة — نعيد ردًا فارغًا\n        asyncContext.addListener(new javax.servlet.AsyncListener() {\n            public void onTimeout(javax.servlet.AsyncEvent event) {\n                WAITING_CLIENTS.remove(asyncContext);\n                try {\n                    HttpServletResponse response = (HttpServletResponse) event.getAsyncContext().getResponse();\n                    response.getWriter().write("timeout");\n                    response.setStatus(HttpServletResponse.SC_OK);\n                    asyncContext.complete();\n                } catch (IOException e) { e.printStackTrace(); }\n            }\n            // تم حذف طرق المستمع الأخرى للاختصار\n        });\n    }\n\n    // يتم استدعاء هذه الطريقة عند ظهور حدث جديد\n    public static void sendEventToClients(String message) {\n        for (AsyncContext ctx : WAITING_CLIENTS) {\n            try {\n                HttpServletResponse response = (HttpServletResponse) ctx.getResponse();\n                response.getWriter().write(message);\n                response.setStatus(HttpServletResponse.SC_OK);\n                ctx.complete();\n                WAITING_CLIENTS.remove(ctx);\n            } catch (IOException e) { e.printStackTrace(); }\n        }\n    }\n}
\n\n

كيف يعمل هذا:

\n
    \n
  • يقوم العميل بإجراء طلب GET إلى /long-poll.
  • \n
  • يقوم الخادم بتحويل الطلب إلى وضع غير متزامن و"ينام" (ينتظر).
  • \n
  • عند ظهور رسالة (طريقة sendEventToClien

المدونات

توصيات الكتب