المشكلة: اتصال خادم العميل وعميل الخادم بوقت استجابة سريع
تم بناء شبكة الويب إلى حد كبير استنادًا إلى ما يُعرف بنموذج الطلب/الاستجابة HTTP. يحمّل العميل صفحة ويب ولا يحدث شيء حتى ينقر المستخدم على الصفحة التالية. في عام 2005 تقريبًا، بدأ استخدام تقنية AJAX لجعل الويب يبدو أكثر ديناميكية. ومع ذلك، تم توجيه جميع اتصالات HTTP بواسطة العميل، ما كان يتطلب تفاعل المستخدم أو البحث الدوري لتحميل بيانات جديدة من الخادم.
يشير ذلك المصطلح إلى التكنولوجيات التي تمكّن الخادم من إرسال البيانات إلى العميل في اللحظة التي يتبيّن فيها أنّ البيانات الجديدة متوفّرة منذ فترة طويلة. وتحمل أسماء مثل "دفع" أو "كوميت". إنّ إحدى عمليات الاختراق الأكثر شيوعًا لإيجاد وهم بشأن اتصال يبدأه الخادم تسمى الاستطلاع الطويل. باستخدام عملية الاستطلاع الطويلة، يفتح العميل اتصال HTTP بالخادم، ما يُبقيه مفتوحًا إلى أن يتم إرسال الاستجابة. وعندما يكون لدى الخادم بيانات جديدة، يرسل الاستجابة الاستجابة (تشمل الأساليب الأخرى استخدام Flash وطلبات XHR متعددة الأجزاء وتُعرف باسم htmlfiles). يعمل الاستطلاع الطويل والتقنيات الأخرى بشكل جيد. يمكنك استخدامها كل يوم في تطبيقات مثل دردشة GMail.
ومع ذلك، تشترك كل هذه الحلول البديلة في مشكلة واحدة: فهي تحمل عبء HTTP، وهو ما لا يجعلها مناسبة تمامًا للتطبيقات ذات وقت الاستجابة السريع. فكِّر في ألعاب الرماية من منظور البطل بين لاعبين متعدّدين في المتصفح أو أي لعبة أخرى على الإنترنت من خلال مكوّن في الوقت الفعلي.
إضافة WebSocket: توفير المقابس على الويب
تحدد مواصفات WebSocket واجهة برمجة تطبيقات تُنشئ اتصالات "socket" بين متصفح ويب وخادم. بعبارة أخرى: هناك اتصال مستمر بين العميل والخادم ويمكن لكلا الطرفين البدء في إرسال البيانات في أي وقت.
البدء
يمكنك فتح اتصال WebSocket ببساطة من خلال استدعاء الدالة الإنشائية WebSocket:
var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
لاحِظ ws:
. هذا هو مخطط عنوان URL الجديد لاتصالات WebSocket. هناك أيضًا wss:
لاتصال WebSocket الآمن بالطريقة نفسها التي يتم بها استخدام https:
لاتصالات HTTP الآمنة.
يتيح لك إرفاق بعض معالِجات الأحداث فورًا بالاتصال إمكانية معرفة وقت فتح الاتصال أو استلام رسائل واردة أو حدوث خطأ.
تقبل الوسيطة الثانية البروتوكولات الفرعية الاختيارية. يمكن أن تكون سلسلة أو مصفوفة من السلاسل. ينبغي أن تمثل كل سلسلة اسم بروتوكول فرعي ويقبل الخادم واحدًا فقط من البروتوكولات الفرعية التي تم تمريرها في المصفوفة. يمكن تحديد البروتوكول الفرعي المقبول من خلال الوصول إلى السمة protocol
في كائن WebSocket.
يجب أن تكون أسماء البروتوكولات الفرعية واحدة من أسماء البروتوكولات الفرعية المسجلة في سجل IANA. لم يتم تسجيل سوى اسم واحد للبروتوكول الفرعي (الصابون) اعتبارًا من شباط (فبراير) 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
. لتحديد تنسيق البرنامج الثنائي الذي تم استلامه، اضبط السمة dualType لكائن WebSocket على "blob" أو "arraybuffer". التنسيق التلقائي هو "blob". (ليس عليك محاذاة مَعلمة للتحقّق من الأولويات عند الإرسال.)
// 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 المفتوحة. يتطلب إبقاء عدد كبير من الاتصالات مفتوحة في نفس الوقت بنية تتلقى تزامن عالٍ بتكلفة منخفضة الأداء. وترتكز هذه البِنى عادةً على سلاسل المحادثات أو ما يسمّى بالإدخال الذي لا يحظره.
عمليات التنفيذ من جهة الخادم
- Node.js
- Java
- ياقوت أحمر
- Python
- إرلانج
- لغة C++
- .NET
إصدارات البروتوكول
أصبح البروتوكول السلكي (المصافحة ونقل البيانات بين العميل والخادم) في WebSocket الآن RFC6455. يتوافق أحدث إصدار من Chrome وChrome لنظام Android بشكل كامل مع RFC6455 بما في ذلك الرسائل الثنائية. وسيتوافق متصفح فايرفوكس مع الإصدار 11 من Internet Explorer في الإصدار 10. وما زال بإمكانك استخدام إصدارات البروتوكول القديمة ولكن لا يُنصح باستخدامها نظرًا إلى كونها عرضة للاختراق. إذا كانت لديك عمليات تنفيذ للخادم للإصدارات الأقدم من بروتوكول WebSocket، نقترح عليك ترقيته إلى أحدث إصدار.
حالات الاستخدام
استخدِم WebSocket متى احتجت إلى وقت استجابة سريع جدًا واتصال في الوقت الفعلي تقريبًا بين العميل والخادم. تجدر الإشارة إلى أنّ ذلك قد يتضمّن إعادة التفكير في كيفية إنشاء التطبيقات من جهة الخادم مع التركيز بشكل جديد على تكنولوجيات مثل قوائم انتظار الأحداث. في ما يلي بعض الأمثلة على حالات الاستخدام:
- ألعاب متعددة اللاعبين على الإنترنت
- تطبيقات الدردشة
- شريط مباريات رياضية مباشرة
- تعديل أحداث البث على وسائل التواصل الاجتماعي في الوقت الفعلي
إصدارات تجريبية
- النقر
- الرسم معي
- Pixelatr
- منقطع
- عدد كبير من الكلمات المتقاطعة التي تتضمّن العديد من اللاعبين على الإنترنت
- خادم Ping (مستخدَم في الأمثلة أعلاه)
- نموذج HTML5demos