إرسال البيانات بين المتصفِّحات باستخدام قنوات بيانات WebRTC

قد تكون عملية إرسال البيانات بين متصفحَين للتواصل أو ممارسة الألعاب أو نقل الملفات معقّدة إلى حدّ ما. ويتطلّب ذلك إعداد خادم ودفع تكلفته لنقل البيانات، وربما توسيع نطاقه ليشمل مراكز بيانات متعددة. في هذا السيناريو، من المحتمل حدوث تأخير كبير، كما يصعب الحفاظ على خصوصية البيانات.

يمكن التخفيف من هذه المشاكل باستخدام واجهة برمجة التطبيقات RTCDataChannel في WebRTC لنقل البيانات مباشرةً من جهاز إلى آخر. تتناول هذه المقالة أساسيات كيفية إعداد قنوات البيانات واستخدامها، بالإضافة إلى حالات الاستخدام الشائعة على الويب اليوم.

لماذا قناة بيانات أخرى؟

لدينا WebSocket وAJAX وServer Sent Events. لماذا نحتاج إلى قناة تواصل أخرى؟ على الرغم من أنّ WebSocket ثنائي الاتجاه، تم تصميم كل هذه التقنيات للتواصل مع خادم أو منه.

تتّبع RTCDataChannel نهجًا مختلفًا:

  • تعمل هذه الميزة مع واجهة برمجة التطبيقات RTCPeerConnection التي تتيح الاتصال بين الأجهزة. يمكن أن يؤدي ذلك إلى تقليل وقت الاستجابة، إذ لا يكون هناك خادم وسيط وعدد أقل من "القفزات".
  • يستخدم RTCDataChannel بروتوكول التحكم في الإرسال عبر البث (SCTP)، ما يتيح إمكانية ضبط دلالات التسليم، مثل التسليم غير المنتظم وإعادة إرسال الإعدادات.

تتوفّر RTCDataChannel الآن مع إمكانية استخدام بروتوكول SCTP على أجهزة الكمبيوتر وأجهزة Android في متصفّحات Google Chrome وOpera وFirefox.

ملاحظة: الإشارات وSTUN وTURN

تتيح WebRTC التواصل بين الأجهزة مباشرةً، ولكنها لا تزال بحاجة إلى خوادم إرسال إشارات لتبادل بيانات الوسائط والشبكة الوصفية من أجل بدء اتصال بين الأجهزة.

يتعامل بروتوكول WebRTC مع ترجمة عنوان الشبكة (NAT) وجدران الحماية من خلال:

  • إطار عمل ICE لتحديد أفضل مسار ممكن للشبكة بين الأجهزة المتصلة بنظام الند للند
  • خوادم STUN لتحديد عنوان IP ومنفذ يمكن الوصول إليهما بشكل علني لكل نظير
  • خوادم TURN في حال تعذّر الاتصال المباشر وكان من الضروري إرسال البيانات

لمزيد من المعلومات حول كيفية عمل WebRTC مع الخوادم لإرسال الإشارات والشبكات، يمكنك الاطّلاع على WebRTC في العالم الحقيقي: STUN وTURN وإرسال الإشارات.

الإمكانات

تتيح واجهة برمجة التطبيقات RTCDataChannel مجموعة مرنة من أنواع البيانات. تم تصميم واجهة برمجة التطبيقات لمحاكاة WebSocket تمامًا، ويتوافق RTCDataChannel مع السلاسل بالإضافة إلى بعض الأنواع الثنائية في JavaScript، مثل Blob وArrayBuffer وArrayBufferView. يمكن أن تكون هذه الأنواع مفيدة عند نقل الملفات وممارسة الألعاب المتعددة اللاعبين.

يمكن أن يعمل RTCDataChannel في الوضع غير الموثوق وغير المنظَّم (مشابه لبروتوكول مخطط بيانات المستخدم أو UDP)، والوضع الموثوق والمنظَّم (مشابه لبروتوكول التحكم في الإرسال أو TCP)، والأوضاع الموثوقة جزئيًا:

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

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

في ما يلي جدول مفيد من كتاب High Performance Browser Networking من تأليف إيليا غريغوريك:

TCPUDPSCTP
الموثوقيةالموثوقيةالتطبيق غير موثوققابلة للضبط
خدمة توصيلتم الطلبغير مرتّبقابلة للضبط
انتقال العدوىموجّه نحو البايتالرسائل الموجّهةالرسائل الموجّهة
التحكّم في التدفقنعملانعم
التحكّم في الازدحامنعملانعم

بعد ذلك، ستتعرّف على كيفية ضبط RTCDataChannel لاستخدام الوضع الموثوق والمرتّب أو الوضع غير الموثوق وغير المرتّب.

إعداد قنوات البيانات

تتوفّر عدة عروض توضيحية بسيطة لـ RTCDataChannel على الإنترنت:

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

الرمز البرمجي اللازم للبدء في استخدام هذه الميزة قصير:

const peerConnection = new RTCPeerConnection();

// Establish your peer connection using your signaling channel here
const dataChannel =
  peerConnection.createDataChannel("myLabel", dataChannelOptions);

dataChannel.onerror = (error) => {
  console.log("Data Channel Error:", error);
};

dataChannel.onmessage = (event) => {
  console.log("Got Data Channel Message:", event.data);
};

dataChannel.onopen = () => {
  dataChannel.send("Hello World!");
};

dataChannel.onclose = () => {
  console.log("The Data Channel is Closed");
};

يتم إنشاء الكائن dataChannel من اتصال أقران تم إنشاؤه مسبقًا. ويمكن إنشاء هذا المعرّف قبل إرسال الإشارات أو بعده. بعد ذلك، يمكنك إدخال تصنيف لتمييز هذه القناة عن غيرها ومجموعة من إعدادات الضبط الاختيارية:

const dataChannelOptions = {
  ordered: false, // do not guarantee order
  maxPacketLifeTime: 3000, // in milliseconds
};

يمكنك أيضًا إضافة الخيار maxRetransmits (عدد المرات التي يجب المحاولة فيها قبل حدوث خطأ)، ولكن يمكنك تحديد maxRetransmits أو maxPacketLifeTime فقط، وليس كليهما. بالنسبة إلى دلالات UDP، اضبط maxRetransmits على 0 وordered على false. لمزيد من المعلومات، يُرجى الاطّلاع على طلبات التعليقات (RFC) الصادرة عن فريق عمل هندسة الإنترنت (IETF) التالية: بروتوكول التحكم في الإرسال عبر البث وإضافة موثوقية جزئية إلى بروتوكول التحكم في الإرسال عبر البث.

  • ordered: ما إذا كانت قناة البيانات يجب أن تضمن الترتيب أم لا
  • maxPacketLifeTime: الحد الأقصى للوقت المتاح لمحاولة إعادة إرسال رسالة لم يتم إرسالها
  • maxRetransmits: الحد الأقصى لعدد المرات التي يمكن فيها محاولة إعادة إرسال رسالة تعذّر إرسالها
  • protocol: يسمح باستخدام بروتوكول فرعي يوفّر معلومات وصفية للتطبيق
  • negotiated: إذا تم ضبطها على "صحيح"، ستتم إزالة الإعداد التلقائي لقناة بيانات على الجهاز الآخر، ما يتيح لك إنشاء قناة بيانات باستخدام المعرّف نفسه على الجهاز الآخر.
  • id: تتيح لك تقديم المعرّف الخاص بك للقناة، ولا يمكن استخدامه إلا مع ضبط negotiated على true)

الخيارات الوحيدة التي يحتاج معظم المستخدمين إلى استخدامها هي الخيارات الثلاثة الأولى: ordered وmaxPacketLifeTime وmaxRetransmits. باستخدام SCTP (الذي تستخدمه الآن جميع المتصفحات المتوافقة مع WebRTC)، يتم تلقائيًا ضبط الإعدادات على "موثوق" و"مرتّب". من المنطقي استخدام خيارَي "غير موثوق به" و"غير مرتّب" إذا كنت تريد التحكّم الكامل من طبقة التطبيق، ولكن في معظم الحالات، تكون الموثوقية الجزئية مفيدة.

يُرجى العِلم أنّه كما هو الحال مع WebSocket، يطلق RTCDataChannel الأحداث عند إنشاء اتصال أو إغلاقه أو حدوث أخطاء، وعندما يتلقّى رسالة من الجهاز الآخر.

هل التحدي آمن؟

التشفير إلزامي لجميع مكونات WebRTC. باستخدام RTCDataChannel، يتم تأمين جميع البيانات باستخدام بروتوكول أمان طبقة النقل لمخطّطات البيانات (DTLS). ‫DTLS هي مشتقة من SSL، ما يعني أنّ بياناتك ستكون آمنة مثل استخدام أي اتصال عادي مستند إلى SSL. تم توحيد بروتوكول أمان طبقة النقل لمخطّطات البيانات (DTLS) وهو مدمج في جميع المتصفّحات التي تتوافق مع WebRTC. لمزيد من المعلومات، يُرجى الاطّلاع على موقع Wireshark الإلكتروني.

تغيير طريقة تفكيرك في البيانات

قد تكون معالجة كميات كبيرة من البيانات من المشاكل الشائعة في JavaScript. كما أشار مطوّرو تطبيق Sharefest، تطلّب ذلك التفكير في البيانات بطريقة جديدة. إذا كنت تنقل ملفًا أكبر من مقدار الذاكرة المتوفّرة لديك، عليك التفكير في طرق جديدة لحفظ هذه المعلومات. وهنا يأتي دور التكنولوجيات، مثل FileSystem API، كما سترى لاحقًا.

إنشاء تطبيق لمشاركة الملفات

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

يجب اتّخاذ عدة خطوات لإجراء عملية نقل ناجحة:

  1. قراءة ملف في JavaScript باستخدام File API
  2. إنشاء اتصال بين الأجهزة باستخدام RTCPeerConnection
  3. إنشاء قناة بيانات بين العملاء باستخدام RTCDataChannel

هناك عدة نقاط يجب مراعاتها عند محاولة إرسال ملفات عبر RTCDataChannel:

  • حجم الملف: إذا كان حجم الملف صغيرًا بشكل معقول ويمكن تخزينه وتحميله ككائن ثنائي كبير (Blob) واحد، يمكنك تحميله في الذاكرة باستخدام File API ثم إرسال الملف عبر قناة موثوقة كما هو (مع الأخذ في الاعتبار أنّ المتصفحات تفرض حدودًا على الحد الأقصى لحجم النقل). كلما زاد حجم الملف، أصبحت الأمور أكثر تعقيدًا. عند الحاجة إلى آلية تقسيم الملفات، يتم تحميل أجزاء الملفات وإرسالها إلى جهاز آخر، مع تضمين البيانات الوصفية chunkID لكي يتمكّن الجهاز الآخر من التعرّف عليها. يُرجى العِلم أنّه في هذه الحالة، عليك أيضًا حفظ الأجزاء أولاً في مساحة التخزين بلا إنترنت (على سبيل المثال، باستخدام FileSystem API) وحفظها على قرص المستخدم فقط عندما يكون لديك الملف بالكامل.
  • حجم الحزمة: هذه هي أصغر "وحدات" البيانات لتطبيقك. يجب تقسيم البيانات إلى حِزم لأنّه يوجد حاليًا حدّ لحجم الإرسال (سيتم إصلاح ذلك في إصدار مستقبلي من قنوات البيانات). الاقتراح الحالي بشأن الحد الأقصى لحجم الأجزاء هو 64 كيلوبايت.

بعد نقل الملف بالكامل إلى الجهة الأخرى، يمكن تنزيله باستخدام علامة ربط:

function saveFile(blob) {
  const link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = 'File Name';
  link.click();
};

تستخدم تطبيقات مشاركة الملفات هذه على PubShare وGitHub هذه التقنية. كلاهما مفتوح المصدر ويوفّر أساسًا جيدًا لتطبيق مشاركة ملفات يستند إلى RTCDataChannel.

إذًا، ما الذي يمكنك فعله؟

تفتح RTCDataChannel الباب أمام طرق جديدة لإنشاء تطبيقات لمشاركة الملفات والألعاب المتعددة اللاعبين وتقديم المحتوى.

  • مشاركة الملفات بين الأجهزة مباشرةً كما هو موضّح سابقًا
  • ألعاب متعدّدة اللاعبين، إلى جانب تقنيات أخرى، مثل WebGL، كما هو موضّح في BananaBread من Mozilla
  • إعادة ابتكار عملية عرض المحتوى من خلال PeerCDN، وهو إطار عمل يعرض مواد عرض الويب من خلال تبادل البيانات بين الأجهزة

تغيير طريقة إنشاء التطبيقات

يمكنك الآن توفير تطبيقات أكثر جاذبية باستخدام اتصالات عالية الأداء ومنخفضة الاستجابة من خلال RTCDataChannel. تسهّل أُطر العمل، مثل PeerJS وPubNub WebRTC SDK، تنفيذ RTCDataChannel، وتتوافق واجهة برمجة التطبيقات الآن مع مجموعة كبيرة من المنصات.

يمكن أن يؤدي ظهور RTCDataChannel إلى تغيير طريقة تفكيرك في نقل البيانات في المتصفّح.

تعرَّف على مزيد من المعلومات