WebSockets في Java: عندما لا يكفي HTTP
\n\nتخيل بورصة عبر الإنترنت. أنت تنظر إلى الرسم البياني لسعر البيتكوين. كل ثانية تتغير الأرقام. أو لعبة متعددة اللاعبين حيث تحرك شخصيتك، ويرى ذلك مئات اللاعبين الآخرين فوراً. أو مجرد دردشة مؤسسية حيث تصل الرسائل دون الضغط على F5.
\n\nكيف يعمل هذا تحت الغطاء؟ في السابق، كان المطورون يلجأون إلى حيل: polling (العميل يرسل طلبات كل ثانية للخادم بسؤال "هل هناك أخبار؟")، long polling (الخادم يبقي الاتصال مفتوحاً حتى يظهر خبر)، Server-Sent Events (تدفق أحادي الاتجاه). كل هذه كانت حلولاً مؤقتة. بروتوكول HTTP صُمم أصلاً كاستجابة لطلب. لا يمكنه "دفع" البيانات بنفسه.
\n\nهنا تأتي WebSockets للإنقاذ. هذا بروتوكول يرفع الاتصال مرة واحدة - ويبقيه مفتوحاً. يمكن للخادم إرسال البيانات إلى العميل في أي لحظة، والعكس صحيح. اتصال ثنائي الاتجاه في الوقت الفعلي، دون حمل زائد لرؤوس HTTP.
\n\nفي هذه المقالة، سنشرح WebSockets في Java من البداية إلى النهاية. سنكتب دردشة كاملة، ونناقش المخاطر الخفية، ونقارن المكتبات الشائعة. إذا كنت مطور Java وتريد إنشاء تطبيقات الوقت الفعلي بلغة Java - فأنت في المكان الصحيح.
\n\nكيف يعمل WebSocket؟ شرح موجز
\n\nWebSocket ليس سحراً، بل مجرد بروتوكول فوق TCP. يبدأ كطلب HTTP عادي (مصافحة)، ثم "يترقى" إلى قناة ثنائية الاتجاه دائمة.
\n\nالمرحلة 1: المصافحة (Handshake)
\nيرسل العميل طلب HTTP GET عادي مع رأس Upgrade: websocket. يستجيب الخادم برمز 101 Switching Protocols. هذا كل شيء. من هذه اللحظة، تنتقل البيانات ليس كحزم HTTP، بل كإطارات WebSocket.
المرحلة 2: إطارات البيانات
\nتُنقل البيانات في حزم صغيرة (إطارات). يمكن أن يكون الإطار نصياً (سلسلة نصية عادية) أو ثنائياً (صورة، صوت). مكتبات Java تخفي هذا التعقيد - أنت تعمل ببساطة مع سلاسل نصية أو بايتات.
\n\nالمرحلة 3: الإغلاق
\nيمكن لأي طرف بدء إغلاق الاتصال عن طريق إرسال إطار Close خاص.
\n\nيبدو بسيطاً؟ هذا صحيح. لكن الشيطان يكمن في التفاصيل: المهلات، إعادة الاتصال، التوسع. لكن سنتحدث عن ذلك لاحقاً.
\n\nمكتبات WebSockets في Java
\n\nفي نظام Java البيئي، هناك ثلاثة طرق رئيسية:
\n\n- \n
- Jakarta WebSocket (JSR 356) - معيار Java EE / Jakarta EE. يعمل على أي خادم متوافق (Tomcat, Jetty, GlassFish). الكثير من التعليقات التوضيحية، القليل من الكود. \n
- Spring WebSocket - طبقة فوق المعيار في نظام Spring البيئي. يوفر التكامل مع Security و STOMP (بروتوكول فوق WebSocket للاشتراك في المواضيع) وقوالب مريحة. \n
- Netty / Vert.x / Undertow - أطر عمل غير متزامنة منخفضة المستوى. أقصى أداء، لكن كود أكثر. \n
لـ 90% من المهام، يكفي Jakarta أو Spring. سننظر في كلا الخيارين مع أمثلة حقيقية.
\n\nمثال 1: دردشة بسيطة باستخدام Jakarta WebSocket (بدون Spring)
\n\nلنفترض أن لدينا Tomcat 10+ (Jakarta EE) قديماً جيداً. نحتاج إلى نقطة نهاية خادم وعميل (HTML+JS).
\n\nالخادم: فئة نقطة النهاية
\nimport jakarta.websocket.*;\nimport jakarta.websocket.server.ServerEndpoint;\nimport java.io.IOException;\nimport java.util.Set;\nimport java.util.concurrent.CopyOnWriteArraySet;\n\n@ServerEndpoint("/chat")\npublic class ChatEndpoint {\n\n // نخزن جميع الجلسات النشطة (مجموعة آمنة للخيوط)\n private static final Set<Session> sessions = new CopyOnWriteArraySet<>();\n\n @OnOpen\n public void onOpen(Session session) {\n sessions.add(session);\n broadcast("مستخدم متصل. العدد الإجمالي في الدردشة: " + sessions.size());\n }\n\n @OnMessage\n public void onMessage(String message, Session session) {\n // يمكن إضافة منطق: إرسال فقط