مقدّمة حول WebSockets: توفير مآخذ الويب

المشكلة: اتصالات منخفضة وقت الاستجابة بين العميل والخادم وبين الخادم والعميل

تم إنشاء الويب إلى حد كبير حول ما يُسمى نموذج الطلب/الاستجابة لبروتوكول HTTP. يحمّل العميل صفحة ويب ثم لا يحدث شيء إلى أن ينقر المستخدم على الصفحة التالية. في عام 2005 تقريبًا، بدأت تقنية AJAX في جعل الويب أكثر ديناميكية. ومع ذلك، كان العميل يوجّه جميع اتصالات HTTP، ما يتطلّب تفاعل المستخدم أو إجراء استطلاع دوري لتحميل بيانات جديدة من الخادم.

إنّ التكنولوجيات التي تتيح للخادم إرسال البيانات إلى العميل في اللحظة التي يعلم فيها أنّ هناك بيانات جديدة متاحة، موجودة منذ فترة طويلة. وتُعرف هذه التقنيات بأسماء مثل "Push" أو "Comet". يُطلق على أحد أكثر الاختراقات شيوعًا لإنشاء وهم اتصال بدأه الخادم اسم الاستقصاء الطويل. باستخدام الاستقصاء الطويل، يفتح العميل اتصال HTTP بالخادم الذي يبقيه مفتوحًا حتى إرسال الاستجابة. وعندما يتوفّر لدى الخادم بيانات جديدة، يرسل الاستجابة (تتضمّن الأساليب الأخرى طلبات Flash وXHR متعددة الأجزاء وما يُعرف باسم ملفات html). تعمل تقنية الاستقصاء الطويل والتقنيات الأخرى بشكل جيد. وتستخدمها كل يوم في تطبيقات مثل المحادثة عبر Gmail.

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

نقدّم لك WebSocket: مآخذ الويب

تحدّد مواصفات WebSocket واجهة برمجة تطبيقات تنشئ اتصالات "مقبس" بين متصفّح ويب وخادم. بعبارة أخرى: هناك اتصال مستمر بين العميل والخادم ويمكن لكلا الطرفين بدء إرسال البيانات في أي وقت.

الخطوات الأولى

يمكنك فتح اتصال WebSocket ببساطة عن طريق استدعاء دالة WebSocket:

var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);

لاحظ ws:. هذا هو مخطّط عنوان URL الجديد لاتصالات WebSocket. هناك أيضًا wss: لاتصال WebSocket الآمن بالطريقة نفسها التي يتم بها استخدام https: لاتصالات HTTP الآمنة.

يتيح لك إرفاق بعض معالجات الأحداث مباشرةً بالاتصال معرفة وقت فتح الاتصال أو تلقّي الرسائل الواردة أو حدوث خطأ.

تقبل الوسيطة الثانية بروتوكولات فرعية اختيارية. ويمكن أن تكون سلسلة أو مصفوفة من السلاسل. يجب أن تمثّل كل سلسلة اسم بروتوكول فرعي، ويقبل الخادم بروتوكولاً فرعيًا واحدًا فقط من البروتوكولات الفرعية التي تم تمريرها في الصفيفة. يمكن تحديد البروتوكول الفرعي المقبول من خلال الوصول إلى السمة protocol لعنصر WebSocket.

يجب أن تكون أسماء البروتوكولات الفرعية أحد أسماء البروتوكولات الفرعية المسجّلة في سجلّ IANA. لا يوجد حاليًا سوى اسم بروتوكول فرعي واحد (soap) مسجّل اعتبارًا من فبراير 2012.

// When the connection is open, send some data to the server
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};

// Log errors
connection.onerror = function (error) {
console.log('WebSocket Error ' + error);
};

// Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};

التواصل مع الخادم

بمجرد اتصالنا بالخادم (عند تنشيط الحدث open)، يمكننا البدء في إرسال البيانات إلى الخادم باستخدام طريقة send('your message') في عنصر الاتصال. كانت تدعم السلاسل فقط، ولكن في أحدث المواصفات، يمكنها الآن إرسال رسائل ثنائية أيضًا. لإرسال بيانات ثنائية، يمكنك استخدام الكائن Blob أو ArrayBuffer.

// Sending String
connection.send('your message');

// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);
for (var i = 0; i < img.data.length; i++) {
binary[i] = img.data[i];
}
connection.send(binary.buffer);

// Sending file as Blob
var file = document.querySelector('input[type="file"]').files[0];
connection.send(file);

وبالمثل، قد يرسل إلينا الخادم رسائل في أي وقت. وعند حدوث ذلك، يتم تنشيط دالة الاستدعاء onmessage. تتلقّى دالة الاستدعاء عنصر حدث، ويمكن الوصول إلى الرسالة الفعلية من خلال السمة data.

يمكن لـ WebSocket أيضًا تلقّي رسائل ثنائية في أحدث المواصفات. ويمكن تلقّي الإطارات الثنائية بتنسيق Blob أو ArrayBuffer. لتحديد تنسيق الملف الثنائي الذي تم تلقّيه، اضبط السمة binaryType لكائن WebSocket على "blob" أو "arraybuffer". التنسيق التلقائي هو "blob". (ليس عليك محاذاة مَعلمة binaryType عند الإرسال).

// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
console.log(e.data.byteLength); // ArrayBuffer object if binary
};

من الميزات الأخرى التي تمت إضافتها مؤخرًا إلى WebSocket هي الإضافات. باستخدام الإضافات، سيكون من الممكن إرسال إطارات مضغوطة ومتعددة وما إلى ذلك. يمكنك العثور على الإضافات التي يقبلها الخادم من خلال فحص سمة الإضافات في عنصر WebSocket بعد حدث الفتح. لا تتوفّر مواصفات رسمية منشورة للإضافات حتى الآن اعتبارًا من فبراير 2012.

// Determining accepted extensions
console.log(connection.extensions);

التواصل المتعدّد المصادر

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

الخوادم الوكيلة

كل تكنولوجيا جديدة تأتي مع مجموعة جديدة من المشاكل. في حالة WebSocket، يكون التوافق مع الخوادم الوكيلة التي تتوسط اتصالات HTTP في معظم شبكات الشركات. يستخدم بروتوكول WebSocket نظام ترقية HTTP (الذي يُستخدم عادةً لبروتوكول HTTP/SSL) من أجل "ترقية" اتصال HTTP إلى اتصال WebSocket. لا تقبل بعض الخوادم الوكيلة ذلك وستقطع الاتصال. وبالتالي، حتى إذا كان عميل معيّن يستخدم بروتوكول WebSocket، قد لا يكون من الممكن إنشاء اتصال. وهذا يجعل القسم التالي أكثر أهمية :)

استخدام WebSockets اليوم

لا تزال WebSocket تقنية حديثة ولم يتم تنفيذها بالكامل في جميع المتصفحات. ومع ذلك، يمكنك استخدام WebSocket اليوم مع المكتبات التي تستخدم إحدى الطرق الاحتياطية المذكورة أعلاه عندما لا يكون WebSocket متاحًا. من المكتبات التي أصبحت شائعة جدًا في هذا المجال socket.io التي تأتي مع تنفيذ بروتوكول من جهة العميل والخادم وتتضمّن إجراءات احتياطية (لا تتيح socket.io المراسلة الثنائية حتى فبراير 2012). هناك أيضًا حلول تجارية مثل PusherApp التي يمكن دمجها بسهولة في أي بيئة ويب من خلال توفير واجهة برمجة تطبيقات HTTP لإرسال رسائل WebSocket إلى العملاء. بسبب طلب HTTP الإضافي، سيكون هناك دائمًا عبء إضافي مقارنةً بـ WebSocket الخالص.

جانب الخادم

يؤدي استخدام WebSocket إلى إنشاء نمط استخدام جديد تمامًا للتطبيقات من جهة الخادم. على الرغم من أنّ حِزم الخوادم التقليدية، مثل LAMP، مصمَّمة حول دورة طلبات HTTP واستجاباتها، فإنّها غالبًا لا تتعامل بشكل جيد مع عدد كبير من اتصالات WebSocket المفتوحة. يتطلب إبقاء عدد كبير من الاتصالات مفتوحة في الوقت نفسه بنية تتلقى تزامنًا عاليًا بتكلفة أداء منخفضة. Such architectures are usually designed around either threading or so called non-blocking IO.

عمليات التنفيذ من جهة الخادم

إصدارات البروتوكول

أصبح بروتوكول الاتصال (تأكيد الاتصال ونقل البيانات بين العميل والخادم) لـ WebSocket الآن RFC6455. يتوافق أحدث إصدار من Chrome وChrome لنظام التشغيل Android تمامًا مع RFC6455، بما في ذلك المراسلة الثنائية. وسيكون Firefox متوافقًا مع الإصدار 11، وInternet Explorer مع الإصدار 10. لا يزال بإمكانك استخدام إصدارات البروتوكول القديمة، ولكن لا يُنصح بذلك لأنّها معرّضة للاختراق. إذا كانت لديك عمليات تنفيذ للخادم لإصدارات قديمة من بروتوكول WebSocket، ننصحك بترقيتها إلى أحدث إصدار.

حالات الاستخدام

استخدِم WebSocket عندما تحتاج إلى اتصال بوقت استجابة منخفض جدًا وفي الوقت الفعلي تقريبًا بين العميل والخادم. يُرجى العِلم أنّ ذلك قد يتطلّب إعادة التفكير في كيفية إنشاء تطبيقات من جهة الخادم مع التركيز بشكل جديد على تقنيات مثل قوائم انتظار الأحداث. في ما يلي بعض الأمثلة على حالات الاستخدام:

  • ألعاب متعددة اللاعبين على الإنترنت
  • تطبيقات الدردشة
  • شريط الأخبار الرياضية المباشرة
  • تعديل خلاصات وسائل التواصل الاجتماعي في الوقت الفعلي

العروض التوضيحية

المراجع