برمجة الشبكات في Kotlin: من المقابس (Sockets) إلى الكوروتينات (Coroutines)

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

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

ابدأ الدورة

برمجة الشبكات في Kotlin: من النظرية إلى التطبيق



العالم الحديث هو عالم من التطبيقات المترابطة. سواء كان روبوت محادثة، لعبة عبر الإنترنت، أو بنية خدمات مصغرة (Microservices) — في جوهر كل ذلك يكمن التفاعل الشبكي. وإذا كانت برمجة الشبكات في الماضي ترتبط حصريًا بـ Java أو C++، فإن Kotlin اليوم تظهر بثقة على الساحة.



لماذا Kotlin بالتحديد؟ هذه اللغة ليست مجرد "Java حديثة". لقد استوعبت أفضل ما في عالم JVM، مضيفةً الإيجاز، الأمان، والدعم القوي للبرمجة غير المتزامنة عبر الكوروتينات (Coroutines). في هذه المقالة، سنشرح كيفية كتابة برمجة الشبكات في Kotlin — من المقابس (Sockets) التقليدية إلى الحلول الأنيقة باستخدام الكوروتينات. ستتعلم كيفية إنشاء خادم TCP الخاص بك، إرسال حزمة UDP، وعدم الجنون بسبب تعدد الخيوط (Multithreading).



لماذا Kotlin مناسبة لمهام الشبكات؟



قبل الغوص في الكود، دعنا نفهم لماذا Kotlin هي خيار ممتاز لـ برمجة الشبكات:



  • التوافق الكامل مع Java: يمكنك استخدام كامل ترسانة java.net و java.nio والأطر الشائعة (Netty, Ktor).
  • الكوروتينات (Coroutines): الكود غير المتزامن يبدو وكأنه متزامن. لا مزيد من جحيم دوال الاسترجاع (Callback Hell).
  • أمان القيم الخالية (Null-safety): فرص أقل للحصول على NullPointerException عند العمل مع تدفقات البيانات.
  • الإضافات الوظيفية (Functional Extensions): دوال إضافية مريحة للعمل مع البايتات والسلاسل النصية.


سنبدأ بالمقابس الأساسية (كما في Java القديمة الجيدة)، ثم ننتقل إلى نهج أكثر حداثة باستخدام الكوروتينات.



الأساسيات: خادم وعميل TCP في Kotlin



لنبدأ بالكلاسيكيات — اتصال TCP. في Kotlin، نستخدم نفس الفئات ServerSocket و Socket، ولكن مع بناء جملة أكثر نظافة.



كتابة خادم صدى (Echo) TCP بسيط



سوف يستقبل خادمنا الرسائل من العميل ويعيد إرسالها مرة أخرى (صدى).



import java.io.BufferedReaderimport java.io.InputStreamReaderimport java.io.PrintWriterimport java.net.ServerSocket

fun main() { val port = 8080 val serverSocket = ServerSocket(port) println("الخادم قيد التشغيل على المنفذ $port")

while (true) { // ننتظر حتى يتصل عميل val clientSocket = serverSocket.accept() println("اتصل عميل: ${clientSocket.inetAddress.hostAddress}")

// نعالج العميل في خيط منفصل (لأغراض تعليمية) Thread { try { val input = BufferedReader(InputStreamReader(clientSocket.inputStream)) val output = PrintWriter(clientSocket.outputStream, true)

var message: String? while (input.readLine().also { message = it } != null) { println("تم الاستلام: $message") output.println("الصدى: $message") } } catch (e: Exception) { println("خطأ: ${e.message}") } finally { clientSocket.close() } }.start() }}


لاحظ: نحن نستخدم Thread { ... }.start(). هذا يعمل، ولكن للإنتاج من الأفضل استخدام مجموعة خيوط (Thread Pool) أو الكوروتينات (سنتحدث عنها لاحقًا).



عميل لخادم الصدى



الآن لنكتب عميلًا يتصل بالخادم ويرسل رسائل:



import java.io.BufferedReaderimport java.io.InputStreamReaderimport java.io.PrintWriterimport java.net.Socket

fun main() { val host = "localhost" val port = 8080

try { val socket = Socket(host, port) val output = PrintWriter(socket.outputStream, true) val input = BufferedReader(InputStreamReader(socket.inputStream))

// نرسل الرسائل val messages = listOf("مرحبًا أيها الخادم!", "كيف حالك؟", "إلى اللقاء!")

المدونات

توصيات الكتب