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

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

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

ابدأ الدورة

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

\n\n

تخيل: أنت تكتب تطبيق دردشة في Kotlin، أو محطة تداول، أو نظام مراقبة خوادم. يحتاج العميل إلى رؤية التغييرات فورًا. طلب HTTP التقليدي "اطلب-ورد" لن يفي بالغرض هنا - يجب أن تصل البيانات من تلقاء نفسها، دون حاجة المستخدم إلى الضغط باستمرار.

\n\n

في عالم Kotlin، هناك طريقتان شائعتان: Long Polling و WebSocket. كلاهما يسمحان بتنظيم تفاعل في الوقت الفعلي، لكنهما يفعلان ذلك بشكل مختلف جوهريًا. أيهما تختار؟ دعنا نفهم ذلك من خلال أمثلة عملية، بدون حشو أو محاضرات أكاديمية.

\n\n

ما هو Long Polling (ولماذا لم يمت)

\n\n

Long Polling هي تقنية يرسل فيها العميل طلب HTTP، ولا يرد الخادم فورًا، بل يظل "معلقًا" مفتوحًا حتى تظهر بيانات جديدة. بمجرد ظهور البيانات - يرسل الخادم الرد، يعالجه العميل ويفتح طلبًا جديدًا على الفور. تتكرر الدورة.

\n\n

يبدو مثل HTTP عادي، ولكن مع مهلة زمنية طويلة. لا توجد بروتوكولات إضافية، ولا مصافحة - كل شيء يعمل فوق HTTP/1.1 أو HTTP/2 القياسي.

\n\n

مثال Long Polling في Kotlin (خادم Ktor + عميل OkHttp)

\n\n

جزء الخادم باستخدام Ktor (سينتظر الخادم حتى تظهر رسالة):

\n\n
import io.ktor.server.engine.*\nimport io.ktor.server.netty.*\nimport io.ktor.server.routing.*\nimport io.ktor.server.response.*\nimport io.ktor.http.*\nimport kotlinx.coroutines.*\n\nfun main() {\n    embeddedServer(Netty, port = 8080) {\n        routing {\n            get("/long-poll") {\n                // محاكاة انتظار رسالة جديدة\n                val message = withContext(Dispatchers.Default) {\n                    delay(5000) // ننتظر 5 ثوانٍ (أو حدث جديد)\n                    "رسالة جديدة: ${System.currentTimeMillis()}"\n                }\n                call.respondText(message, ContentType.Text.Plain)\n            }\n        }\n    }.start(wait = true)\n}\n
\n\n

العميل باستخدام OkHttp:

\n\n
import okhttp3.*\n\nval client = OkHttpClient.Builder()\n    .readTimeout(30, TimeUnit.SECONDS) // نقطة مهمة!\n    .build()\n\nfun startLongPolling() {\n    val request = Request.Builder()\n        .url("http://localhost:8080/long-poll")\n        .build()\n\n    client.newCall(request).enqueue(object : Callback {\n        override fun onFailure(call: Call, e: IOException) {\n            e.printStackTrace()\n            // يجب إعادة تشغيل polling عند حدوث خطأ\n            startLongPolling()\n        }\n\n        override fun onResponse(call: Call, response: Response) {\n            response.use {\n                if (response.isSuccessful) {\n                    println("تم الاستلام: ${response.body?.string()}")\n                    // نبدأ الطلب التالي فورًا\n                    startLongPolling()\n                }\n            }\n        }\n    })\n}\n
\n\n

إيجابيات Long Polling:

\n
    \n
  • يعمل في كل مكان، حتى خلف البروكسيات المؤسسية وفي المتصفحات القديمة
  • \n
  • تصحيح الأخطاء بسيط - ترى طلبات HTTP عادية في السجلات
  • \n
  • سهولة التكامل مع البنية التحتية الحالية (موازنات التحميل، التخزين المؤقت، CDN)
  • \n
\n\n

سلبيات:

\n
    \n
  • زمن استجابة عالي - قد يمر وقت RTT (زمن الرحلة ذهابًا وإيابًا) بين إرسال الطلب واستلام الرد
  • \n
  • الخادم يحتفظ بالعديد من الاتصالات المفتوحة (كل طلب هو مؤشر ترابط/كوروتين منفصل)
  • \n
  • احتمال فقدان الرسائل عند إعادة الاتصال (إذا لم يتم تنفيذ خاصية التطابق)
  • \n
\n\n

WebSocket: ازدواج كامل

\n\n

WebSocket هو بروتوكول منفصل (ws://) ينشئ اتصالًا ثنائي الاتجاه دائمًا بعد مصافحة HTTP. يمكن للخادم والعميل إرسال الرسائل في أي وقت، بدون حمل زائد للرؤوس.

\n\n

مثال WebSocket في Kotlin (خادم Ktor + عميل Ktor)

المدونات

توصيات الكتب