كيف تستخدم Websocket مع واجهة برمجة تطبيقات Express بسيطة؟

وصف موجز للتكنولوجيا



Websocket هو بروتوكول اتصال عبر اتصال TCP ، مصمم لتبادل الرسائل بين المستعرض وخادم الويب في الوقت الفعلي.



يستخدم العميل والخادم بروتوكولًا مشابهًا لـ HTTP لإنشاء اتصال WebSocket. يقوم العميل بعمل طلب HTTP خاص يستجيب له الخادم بطريقة معينة.



ملاحظات



بالرغم من أن الطلبات والاستجابات الجديدة "مشابهة" لطلبات واستجابات HTTP ، إلا أنها ليست كذلك. على سبيل المثال ، يحتوي الطلب على نص ، ولكن لا يوجد حقل "طول المحتوى" في الرؤوس (مما يخالف قواعد HTTP). يمكنك قراءة المزيد عن هذا في ويكيبيديا .



تتمثل إحدى المزايا الرئيسية للتكنولوجيا في بساطتها. لا يوجد سوى 4 أحداث على العميل والخادم لمعالجة:



  1. الإتصال
  2. خطأ
  3. رسالة
  4. أغلق


لماذا Websocket؟



بالإضافة إلى ws ، هناك طريقتان أخريان لنقل البيانات المستمر: الأحداث المرسلة من الخادم (SSE) والاستقصاء الطويل.



دعنا نقارن آليات الاتصال المستمر بين الخادم والعميل ، ونستخلص أيضًا استنتاجات حول سبب استخدام مقبس ويب (أو عدم جدواه).



مقبس ويب sse تجميع طويل
بروتوكول websocket (ws ، أو wss) HTTP (S) HTTP (S)
سرعة عالي منخفض منخفض
اتجاهية تدفقات البيانات ثنائي الاتجاه أحادي الاتجاه ثنائي الاتجاه
بالإضافة إلى نقل البيانات الثنائية ، لا

يوجد دعم لبعض المتصفحات القديمة
إعادة الاتصال التلقائي عند انقطاع الاتصال


واحدة من المزايا الرئيسية لتكنولوجيا ws هي سرعة نقل البيانات. يستخدم SSE و LP بروتوكول HTTP (S) ويعملان شيئًا كالتالي:



  1. تقديم طلب لإجراء تغييرات ؛
  2. إذا ظهرت التغييرات على الخادم ، يرسلها الخادم ؛
  3. , .


:



  1. .
  2. , HTTP(S).
  3. , .


api.



const http = require("http");
const express = require( "express");
const WebSocket = require( "ws");

const app = express();

const server = http.createServer(app);

const webSocketServer = new WebSocket.Server({ server });

webSocketServer.on('connection', ws => {
   ws.on('message', m => {
webSocketServer.clients.forEach(client => client.send(m));
   });

   ws.on("error", e => ws.send(e));

   ws.send('Hi there, I am a WebSocket server');
});

server.listen(8999, () => console.log("Server started"))


ماذا يحدث هنا؟



لإنشاء خادم يدعم ws ، نقوم بإنشاء خادم http عادي ، ثم نربط الخادم به عند إنشاء مقبس ويب.



تساعد وظيفة "on" في إدارة أحداث websocket. أهم حدث هو حدث الرسالة ، لذلك دعونا نلقي نظرة فاحصة عليه.



هنا تستقبل الوظيفة المعلمة m - الرسالة ، أي ما أرسله المستخدم. وبالتالي ، يمكننا إرسال سلسلة من العميل ومعالجتها على الخادم. في هذه الحالة ، يقوم الخادم ببساطة بإعادة توجيه هذه الرسالة إلى كل شخص متصل بخادم websocket. تحتوي مجموعة العملاء الخاصة بكائن webSocketServer على كافة الاتصالات بالخادم. يقوم الكائن ws بتخزين اتصال واحد فقط في كل مرة.



تعليق



يجب ألا تستخدم هذا الأسلوب في تطبيق حقيقي. إذا وصفت api بهذه الطريقة ، فلن يتمكن الخادم من التمييز بين طلب وآخر. كيف يمكنك بناء API على أساس websocket سيتم كتابتها لاحقًا.



سيبدو التفاعل مع الخادم على العميل كما يلي:



export const wsConnection = new WebSocket("ws://localhost:8999");
wsConnection.onopen = function() {
    alert(" .");
};

wsConnection.onclose = function(event) {
    if (event.wasClean) {
        alert('  ');
    } else {
        alert(' '); // , ""  
    }
    alert(': ' + event.code + ' : ' + event.reason);
};

wsConnection.onerror = function(error) {
    alert(" " + error.message);
};

export const wsSend = function(data) {
// readyState - true,   
    if(!wsConnection.readyState){
        setTimeout(function (){
            wsSend(data);
        },100);
    } else {
        wsConnection.send(data);
    }
};


API على أساس Websocket



على عكس REST API ، حيث يتم توزيع الطلبات عبر عناوين URL مختلفة ، فإن Websocket API لها عنوان URL واحد فقط. من أجل إنشاء واجهة برمجة تطبيقات كاملة تستند إلى مآخذ ويب ، تحتاج إلى تعليم النظام التمييز بين طلب وآخر. يمكن تنفيذ ذلك على النحو التالي:



1) من العميل ، سنرسل الطلبات في شكل سلسلة json ، والتي سنقوم بتحليلها على الخادم:



const sendMessage = (message) => conn.send(JSON.stringify({ event: "chat-message", payload: { userName, message }}));


2) على الخادم ، نقوم بتحليل السلسلة واختيار حقل الحدث - نوع الطلب. دعنا نكتب الإجابة المقابلة لكل نوع:



const dispatchEvent = (message, ws) => {
   const json = JSON.parse(message);
   switch (json.event) {
       case "chat-message": webSocketServer.clients.forEach(client => client.send(message));
       default: ws.send((new Error("Wrong query")).message);
   }
}


وبالتالي ، يمكننا إرسال طلبات مختلفة إلى الخادم ومعالجة الاستجابة حسب الطلب.



خاتمة



إذا تم تكليفك بمهمة إنشاء واجهة برمجة تطبيقات واكتشفت أن العميل غير مهتم بدعم المتصفحات القديمة ، فإن واجهة برمجة التطبيقات المستندة إلى WebSocket هي خيار ممتاز. من أجل راحتك ، قمنا بإعداد الكود الخاص بأجزاء العميل والخادم على الرابط .



All Articles