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

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

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

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

لدينا WebSocket وAJAX وأحداث مُرسَلة من الخادم. لماذا نحتاج إلى قناة اتصال أخرى؟ WebSocket ثنائي الاتجاه، ولكن تم تصميم كل هذه التقنيات للتواصل مع خادم أو من خادم.

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

  • وهي تعمل مع واجهة برمجة التطبيقات RTCPeerConnection API التي تتيح الاتصال من جهاز إلى آخر. وقد يؤدي ذلك إلى انخفاض وقت الاستجابة، أي عدم استخدام خادم وسيط وعدد أقل من "القفزات".
  • يستخدم 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. لمزيد من المعلومات، يُرجى الاطّلاع على مخطّطات IETF RFC التالية: بروتوكول التحكّم في نقل البث وإضافة موثوقية جزئية إلى بروتوكول التحكّم في نقل البث.

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

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

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

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

التشفير إلزامي لجميع مكوّنات WebRTC. باستخدام RTCDataChannel، يتم تأمين جميع البيانات باستخدام أمان طبقة النقل لمخطّطات البيانات (DTLS). ‫DTLS هو مشتق من طبقة المقابس الآمنة، ما يعني أنّ بياناتك ستكون آمنة تمامًا مثل استخدام أي اتصال عادي يستند إلى طبقة المقابس الآمنة. بروتوكول 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 إلى تغيير طريقة تفكيرك في نقل البيانات في المتصفّح.

التعرف على المزيد