برمجة الشبكات باستخدام TypeScript: من المقابس (Sockets) إلى WebSocket
\n\nعندما نتحدث عن برمجة الشبكات باستخدام TypeScript، غالبًا ما نتخيل أنظمة موزعة معقدة، أو غرف دردشة فورية، أو خوادم ألعاب. وهذا ليس من قبيل الصدفة: فـ TypeScript مع كتابته الصارمة (Strict Typing) وإمكانيات التحليل الثابت (Static Analysis) يجعل تطوير تطبيقات الشبكات ليس آمنًا فحسب، بل مريحًا حقًا.
\n\nفي هذه المقالة، سنشرح كيفية إنشاء تطبيقات خادم-عميل (Client-Server) باستخدام TypeScript، مستخدمين الوحدات المدمجة في Node.js — net و dgram — بالإضافة إلى مكتبات العمل مع WebSocket. ستحصل على أمثلة كود جاهزة يمكنك تطبيقها فورًا في مشاريعك.
لماذا TypeScript لبرمجة الشبكات؟
\n\nاعتاد العديد من المطورين على استخدام JavaScript للواجهة الخلفية (Backend)، لكن برمجة الشبكات باستخدام TypeScript تقدم عدة مزايا:
\n\n- \n
- كتابة البيانات (Typing) — تحدد مسبقًا بنية الحزم والرسائل \n
- الإكمال التلقائي (Autocompletion) — تقترح بيئة التطوير المتكاملة (IDE) دوال المقابس ومعاملاتها \n
- أخطاء أقل — يكتشف المترجم (Compiler) عدم تطابق الأنواع قبل التشغيل \n
لنلقِ نظرة على مثال حقيقي. تخيل أننا نكتب خادم TCP. في JavaScript، ستكتب:
\n\nconst server = require('net').createServer(socket => {\n socket.on('data', data => {\n // data هو Buffer، يجب تذكر ذلك\n });\n});\n\nأما في TypeScript، نحصل على أنواع واضحة:
\n\nimport * as net from 'net';\n\nconst server: net.Server = net.createServer((socket: net.Socket) => {\n socket.on('data', (data: Buffer) => {\n // النوع Buffer معروف، نعمل بثقة\n });\n});\n\nقد يبدو هذا تفصيلًا صغيرًا، لكنه في المشاريع الكبيرة يوفر ساعات من التصحيح (Debugging).
\n\nالأساسيات: خادم TCP وعميل باستخدام TypeScript
\n\nلنبدأ بالكلاسيكيات — TCP. سننشئ خادم صدى (Echo Server) بسيطًا يعيد للعميل ما استقبله.
\n\nخادم TCP
\n\nimport * as net from 'net';\n\nconst PORT: number = 3000;\nconst HOST: string = '127.0.0.1';\n\nconst server: net.Server = net.createServer((socket: net.Socket) => {\n console.log(`اتصل عميل: ${socket.remoteAddress}:${socket.remotePort}`);\n\n socket.on('data', (data: Buffer) => {\n const message: string = data.toString().trim();\n console.log(`تم الاستلام: ${message}`);\n socket.write(`الصدى: ${message}\\n`);\n });\n\n socket.on('end', () => {\n console.log('فصل العميل');\n });\n\n socket.on('error', (err: Error) => {\n console.error('خطأ في المقبس:', err.message);\n });\n});\n\nserver.listen(PORT, HOST, () => {\n console.log(`خادم TCP يعمل على ${HOST}:${PORT}`);\n});\n\nلاحظ: قمنا بكتابة (Typing) جميع المتغيرات — server، socket، data، err. هذا يتيح لنا رؤية الدوال المتاحة للمقبس وتجنب الأخطاء العرضية.
عميل TCP
\n\nimport * as net from 'net';\n\nconst client: net.Socket = new net.Socket();\n\nclient.connect(3000, '127.0.0.1', () => {\n console.log('متصل بالخادم');\n client.write('مرحبًا أيها الخادم!');\n});\n\nclient.on('data', (data: Buffer) => {\n console.log('رد الخادم:', data.toString());\n client.destroy();\n});\n\nclient.on('close', () => {\n console.log('تم إغلاق الاتصال');\n});\n\nيمكن تشغيل هذا الكود في أي مشروع Node.js مع TypeScript. فقط قم بتثبيت @types/node وقم بالتجميع (Compile).
UDP: عندما تكون السرعة أهم من الموثوقية
\n\nإذا كنت بحاجة لنقل البيانات دون إنشاء اتصال (على سبيل المثال، للبث المباشر أو الألعاب)، استخدم مقابس UDP في TypeScript. توفر الوحدة dgram كل ما تحتاجه.
خادم UDP
\n\nimport * as dgram from 'dgram';\n\nconst server: dgram.Socke