اتصالات التطبيقات المشابهة هي جزء من مواصفات WebRTC التي تتعامل مع
توصيل تطبيقين على حواسيب مختلفة للاتصال باستخدام
بروتوكول نظير إلى نظير. يمكن أن يكون التواصل بين الأقران فيديو أو صوتًا أو
بيانات ثنائية عشوائية (للعملاء الذين يتيحون استخدام RTCDataChannel
API) ضِمن
لاكتشاف كيف يمكن لزميلين آخرين التواصل، يحتاج كلا العميلين إلى تقديم تقرير ICE
إعداد الخادم هذا إما STUN أو خادم turn-server، ويكون دورهما
لتوفير عناصر ICE المحفّزة لعرض الإعلان لكل عميل يتم نقله بعد ذلك إلى جهاز التحكّم عن بُعد
زميل. وعادة ما يُطلق على عملية نقل العناصر المرشّحة لمركز ICE اسم الإشارة.
الإشارة
تتضمن مواصفات WebRTC واجهات برمجة التطبيقات للاتصال بمركز ICE (الإنترنت إنشاء الاتصال) الخادم، ولكن مكون الإشارة ليس جزءًا من بها. هناك حاجة إلى الإشارة حتى يتمكن اثنان من الزملاء من مشاركة كيفية التواصل. عادةً ما يتم حل هذه المشكلة من خلال واجهة برمجة تطبيقات ويب عادية تستند إلى HTTP (أي REST). أو آلية استدعاء إجراء عن بُعد أخرى) حيث يمكن لتطبيقات الويب ترحيل البيانات اللازمة المعلومات قبل بدء اتصال النظير.
ويوضح مقتطف الرمز التالي كيف يمكن استخدام خدمة الإشارات الوهمية هذه إرسال الرسائل واستلامها بشكل غير متزامن. وسيتم استخدام ذلك في الوحدات المتبقية الأمثلة في هذا الدليل عند الضرورة.
// Set up an asynchronous communication channel that will be
// used during the peer connection setup
const signalingChannel = new SignalingChannel(remoteClientId);
signalingChannel.addEventListener('message', message => {
// New message from remote client received
});
// Send an asynchronous message to the remote client
signalingChannel.send('Hello!');
يمكن تنفيذ الإشارة بعدة طرق مختلفة، ويمكن من خلال WebRTC المواصفات لا تفضل أي حل معين.
بدء اتصالات الزملاء
يتعامل عنصر RTCPeerConnection
مع كل اتصال نظير. الدالة الإنشائية
في هذه الفئة، يتم استخدام كائن RTCConfiguration
واحد كمَعلمته. هذا النمط
يحدد كيفية إعداد اتصال النظير ويجب أن يحتوي على معلومات
لخوادم ICE.
بعد إنشاء RTCPeerConnection
، نحتاج إلى إنشاء عرض SDP أو
إجابتك، اعتمادًا على ما إذا كنا الزملاء المتصلين أو الذين نستقبلهم. بمجرد إجراء وصف الفيديو (SDP)
عرض أو إجابة، فيجب إرسالها إلى الزميل البعيد من خلال
قناة مختلفة. يسمى تمرير كائنات SDP إلى أقران بعيدين بالإشارة
لا تشملها مواصفات WebRTC.
لبدء إعداد اتصال الأقران من جانب الاتصال، ننشئ
كائن RTCPeerConnection
ثم استدعاء createOffer()
لإنشاء
كائن RTCSessionDescription
. تم ضبط وصف الجلسة هذا على الإعداد المحلي.
الوصف باستخدام setLocalDescription()
، ثم يتم إرساله عبر الإشارات
إلى الطرف المستلم. نقوم أيضًا بإعداد أداة استماع لإشاراتنا
عند تلقّي إجابة عن وصف الجلسة المقدّمة من
الجانب المستلم.
async function makeCall() {
const configuration = {'iceServers': [{'urls': 'stun:stun.l.google.com:19302'}]}
const peerConnection = new RTCPeerConnection(configuration);
signalingChannel.addEventListener('message', async message => {
if (message.answer) {
const remoteDesc = new RTCSessionDescription(message.answer);
await peerConnection.setRemoteDescription(remoteDesc);
}
});
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
signalingChannel.send({'offer': offer});
}
على الجانب المستلم، ننتظر عرضًا واردًا قبل إنشاء
مثال واحد (RTCPeerConnection
) بعد الانتهاء، نضبط العرض الذي تم استلامه باستخدام
setRemoteDescription()
بعد ذلك، نسمي createAnswer()
لإنشاء إجابة على
العرض الذي تم استلامه. تم ضبط هذه الإجابة كوصف محلي باستخدام
setLocalDescription()
ثم تم إرسالها إلى جهة الاتصال من خلال الإشارة.
الخادم.
const peerConnection = new RTCPeerConnection(configuration);
signalingChannel.addEventListener('message', async message => {
if (message.offer) {
peerConnection.setRemoteDescription(new RTCSessionDescription(message.offer));
const answer = await peerConnection.createAnswer();
await peerConnection.setLocalDescription(answer);
signalingChannel.send({'answer': answer});
}
});
بمجرد تعيين الزميلين لأوصاف الجلسات المحلية والبعيدة، تعرف إمكانات الزملاء البعيدين. هذا لا يعني أن الاتصال بين الأقران جاهز. نحتاج إلى جمع بيانات ICE المرشحين لكل جهة اتصال وانتقالها (عبر القناة التي ترسل إشارات) إلى أخرى زميل.
مرشّحو ICE
قبل أن يتمكن اثنين من الزملاء من التواصل باستخدام WebRTC، فإنهما بحاجة إلى تبادل معلومات الاتصال. ونظرًا لأن ظروف الشبكة قد تختلف حسب مجموعة من العوامل، فعادةً ما يتم استخدام خدمة خارجية لاكتشاف المرشحين المحتملين للاتصال بأحد الزملاء. وتسمّى هذه الخدمة ICE باستخدام خادم STUN أو turn. الاختصار STUN يعني اجتياز الجلسة برامج خدمات لترجمة عنوان الشبكة (NAT)، وتُستخدم عادةً بشكل غير مباشر في معظم تطبيقات WebRTC.
ويشكّل بروتوكول turn (الاجتياز باستخدام بروتوكول ترجمة عنوان الشبكة (NAT) الحل الأكثر تقدمًا الذي يجمع بين
بروتوكولات STUN ومعظم الخدمات التجارية المستندة إلى WebRTC والتي تستخدم خادم ADD
لإنشاء روابط بين الأقران. تتوافق واجهة برمجة تطبيقات WebRTC مع STUN.
وتحوّل بشكل مباشر، ويتم تجميعها ضمن مصطلح "الإنترنت" الأكثر اكتمالاً
تأسيس الاتصال. عند إنشاء اتصال WebRTC، عادةً ما
توفير خادم أو أكثر من خوادم ICE في إعدادات
عنصر RTCPeerConnection
.
Trickle ICE
بعد إنشاء عنصر RTCPeerConnection
، يستخدم إطار العمل الأساسي
تقديم خوادم ICE لجمع المرشحين لإنشاء إمكانية الاتصال (ICE
المرشحين). الحدث icegatheringstatechange
في إشارات RTCPeerConnection
حسب حالة جمع ICE (new
أو gathering
أو complete
).
وفي حين أنه من الممكن أن ينتظر أحد الزملاء حتى يكتمل جمع ICE، فإنه أكثر كفاءة عادةً في استخدام "شكل ثلجي خفيف" الأسلوب والنقل لكل مرشح ICE إلى النظراء البعيد عند اكتشافه. سيؤدي هذا إلى إلى تقليل وقت إعداد الاتصال بالشبكة المشابهة بشكل كبير والسماح بتشغيل اتصالاً للبدء بتأخيرات أقل.
لجمع مرشّحين من ICE، ما عليك سوى إضافة أداة استماع إلى حدث "icecandidate
".
ستتضمّن قيمة RTCPeerConnectionIceEvent
المنبعثة من ذلك المستمع
السمة candidate
التي تمثّل مرشحًا جديدًا يجب إرساله إلى
نظير بعيد (راجِع الإشارة).
// Listen for local ICE candidates on the local RTCPeerConnection
peerConnection.addEventListener('icecandidate', event => {
if (event.candidate) {
signalingChannel.send({'new-ice-candidate': event.candidate});
}
});
// Listen for remote ICE candidates and add them to the local RTCPeerConnection
signalingChannel.addEventListener('message', async message => {
if (message.iceCandidate) {
try {
await peerConnection.addIceCandidate(message.iceCandidate);
} catch (e) {
console.error('Error adding received ice candidate', e);
}
}
});
تم إنشاء اتصال
فور تلقّي المرشحين لمركز ICE، علينا أن نتوقّع أن يحصل أي من الطرفين على الولاية
سوف يتغير الاتصال في النهاية إلى حالة متصل. لاكتشاف ذلك، نضيف
المستمع إلى RTCPeerConnection
حيث نستمع إلى connectionstatechange
أحداث.
// Listen for connectionstatechange on the local RTCPeerConnection
peerConnection.addEventListener('connectionstatechange', event => {
if (peerConnection.connectionState === 'connected') {
// Peers connected!
}
});