ما هو الإرسال؟
الإشارات هي عملية تنسيق الاتصالات. لكي يتمكّن تطبيق WebRTC من إعداد مكالمة، يجب أن يتبادل العملاء المعلومات التالية:
- رسائل التحكّم في الجلسة المستخدَمة لفتح الاتصال أو إغلاقه
- رسائل الخطأ
- البيانات الوصفية للوسائط، مثل برامج الترميز وإعدادات برامج الترميز ومعدل نقل البيانات وأنواع الوسائط
- بيانات المفاتيح المستخدَمة لإنشاء اتصالات آمنة
- بيانات الشبكة، مثل عنوان IP والمنفذ الخاصَين بالمضيف كما يظهران للعالم الخارجي
وتتطلّب عملية الإرسال هذه طريقة تتيح للعملاء إرسال الرسائل ذهاباً وإيابًا. لا تطبّق واجهات برمجة تطبيقات WebRTC هذه الآلية. عليك إنشاء النموذج بنفسك. ستتعرّف لاحقًا في هذه المقالة على طرق إنشاء خدمة إرسال إشارات. أولاً، عليك معرفة بعض المعلومات.
لماذا لا يحدِّد WebRTC عملية الإرسال والاستقبال؟
لتجنُّب التكرار وتحقيق أقصى قدر من التوافق مع التقنيات الراسخة، لا تحدّد معايير WebRTC طرق الإرسال والبروتوكولات. يوضّح بروتوكول إنشاء جلسة JavaScript (JSEP) هذا النهج:
تتجنّب بنية JSEP أيضًا أن يضطر المتصفّح إلى حفظ الحالة، أي أن يعمل كآلة حالة للإشارات. سيكون ذلك مشكلة إذا فقدت بيانات الإشارات، على سبيل المثال، في كل مرة تتم فيها إعادة تحميل الصفحة. بدلاً من ذلك، يمكن حفظ حالة الإرسال على خادم.
يتطلّب JSEP تبادل offer وanswer، وهما السمتَان الوصفيتان للوسائط المذكورتان أعلاه، بين الأجهزة المشابهة. يتم إرسال عروض الجلسات واستلامها بتنسيق بروتوكول وصف الجلسة (SDP)، الذي يبدو على النحو التالي:
v=0
o=- 7614219274584779017 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio video
a=msid-semantic: WMS
m=audio 1 RTP/SAVPF 111 103 104 0 8 107 106 105 13 126
c=IN IP4 0.0.0.0
a=rtcp:1 IN IP4 0.0.0.0
a=ice-ufrag:W2TGCZw2NZHuwlnf
a=ice-pwd:xdQEccP40E+P0L5qTyzDgfmW
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=mid:audio
a=rtcp-mux
a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:9c1AHz27dZ9xPI91YNfSlI67/EMkjHHIHORiClQe
a=rtpmap:111 opus/48000/2
…
هل تريد معرفة ما تعنيه كل هذه المصطلحات المعقدة في بروتوكول وصف الجلسة (SDP)؟ اطّلِع على أمثلة مجموعة مهندسي شبكة الإنترنت (IETF).
يُرجى العِلم أنّه تم تصميم WebRTC بحيث يمكن تعديل العرض أو الإجابة قبل ضبطهما كوصف محلي أو عن بُعد من خلال تعديل القيم في نص SDP. على سبيل المثال، يمكن استخدام الدالة preferAudioCodec()
في appr.tc لضبط برنامج الترميز ومعدل نقل البيانات التلقائيَين. من الصعب إلى حدٍ ما التلاعب بتنسيق SDP باستخدام JavaScript، وهناك نقاش حول ما إذا كان يجب أن تستخدم الإصدارات المستقبلية من WebRTC تنسيق JSON بدلاً من ذلك، ولكن هناك بعض المزايا التي تدفعك إلى الاستمرار في استخدام SDP.
RTCPeerConnection
واجهة برمجة التطبيقات والإشارات: العرض والإجابة والمرشّح
RTCPeerConnection
هي واجهة برمجة التطبيقات التي تستخدمها تطبيقات WebRTC لإنشاء اتصال بين الأجهزة المشابهة، ونقل الصوت والفيديو.
لبدء هذه العملية، تتضمّن RTCPeerConnection
مهمتَين:
- تأكَّد من شروط الوسائط المحلية، مثل درجة الدقة وإمكانات ترميز الفيديو. هذه هي البيانات الوصفية المستخدَمة في آلية العرض والإجابة.
- الحصول على عناوين الشبكة المحتملة لمضيف التطبيق، والتي تُعرف باسم المرشحين
بعد التأكّد من صحة هذه البيانات المحلية، يجب تبادلها من خلال آلية إرسال إشارات مع المثيّر البعيد.
لنفترض أنّ أسيل تحاول الاتصال بـ "إيناس". في ما يلي آلية العرض/الإجابة الكاملة بكل تفاصيلها المفصّلة:
- تنشئ "ألين" عنصر
RTCPeerConnection
. - تنشئ "ليلى" عرضًا (وصف جلسة SDP) باستخدام طريقة
RTCPeerConnection
createOffer()
. - تتصل "أليس" برقم
setLocalDescription()
لتقديم عرضها. - تحوّل "أليس" العرض إلى سلسلة وتستخدم آلية إرسال إشارات لإرساله إلى "إيفان".
- تتصل "إيفان" بـ "
setRemoteDescription()
" لإطلاعها على عرض "أليس"، حتى يتعرّف "RTCPeerConnection
" على عملية الإعداد التي أجرتها "أليس". - تتصل "إيفانا" بـ
createAnswer()
ويتم تمرير وصف الجلسة المحلية إلى دالة الاستدعاء الناجحة لهذا الإجراء، وهو إجابة "إيفانا". - تضبط "إيفانا" إجابتها كوصف محلي من خلال الاتصال برقم
setLocalDescription()
. - بعد ذلك، تستخدم "آية" آلية الإرسال لإرسال إجابتها المُشفَّرة إلى "أليس".
- تضبط "منى" إجابة "هند" كوصف للجلسة البعيدة باستخدام
setRemoteDescription()
.
تحتاج "ليلى" و"هند" أيضًا إلى تبادل معلومات الشبكة. يشير التعبير "العثور على قنوات اتصال محتملة" إلى عملية العثور على واجهات الشبكة والمنافذ باستخدام إطار عمل ICE.
- تنشئ "ليلى" عنصر
RTCPeerConnection
باستخدام معالِجonicecandidate
. - يتمّ استدعاء معالِج الطلبات عندما تصبح مرشّحات الشبكات متاحة.
- في المعالج، تُرسِل "ليلى" بيانات المرشحين التي تم تحويلها إلى سلسلة إلى "هناء" من خلال قناة الإشارات.
- عندما تتلقّى "آية" رسالة مرشحة من "أليس"، تتصل بـ
addIceCandidate()
لإضافة المرشح إلى وصف الخادم البعيد.
يتيح بروتوكول JSEP ميزة ICE Candidate Trickling، التي تسمح للمتصل بتقديم مرشحين تدريجيًا للمُتصل إليه بعد العرض الأولي، وللمُتصل إليه ببدء التفاعل مع المكالمة وإعداد اتصال بدون انتظار وصول جميع المرشحين.
رمز WebRTC لإرسال الإشارات
مقتطف الرمز البرمجي التالي هو مثال على رمز W3C يلخّص عملية الإرسال الكاملة. يفترض الرمز البرمجي توفُّر آلية إرسال إشارات، SignalingChannel
. سنناقش الإشارات بمزيد من التفصيل لاحقًا.
// handles JSON.stringify/parse
const signaling = new SignalingChannel();
const constraints = {audio: true, video: true};
const configuration = {iceServers: [{urls: 'stun:stun.example.org'}]};
const pc = new RTCPeerConnection(configuration);
// Send any ice candidates to the other peer.
pc.onicecandidate = ({candidate}) => signaling.send({candidate});
// Let the "negotiationneeded" event trigger offer generation.
pc.onnegotiationneeded = async () => {
try {
await pc.setLocalDescription(await pc.createOffer());
// send the offer to the other peer
signaling.send({desc: pc.localDescription});
} catch (err) {
console.error(err);
}
};
// After remote track media arrives, show it in remote video element.
pc.ontrack = (event) => {
// Don't set srcObject again if it is already set.
if (remoteView.srcObject) return;
remoteView.srcObject = event.streams[0];
};
// Call start() to initiate.
async function start() {
try {
// Get local stream, show it in self-view, and add it to be sent.
const stream =
await navigator.mediaDevices.getUserMedia(constraints);
stream.getTracks().forEach((track) =>
pc.addTrack(track, stream));
selfView.srcObject = stream;
} catch (err) {
console.error(err);
}
}
signaling.onmessage = async ({desc, candidate}) => {
try {
if (desc) {
// If you get an offer, you need to reply with an answer.
if (desc.type === 'offer') {
await pc.setRemoteDescription(desc);
const stream =
await navigator.mediaDevices.getUserMedia(constraints);
stream.getTracks().forEach((track) =>
pc.addTrack(track, stream));
await pc.setLocalDescription(await pc.createAnswer());
signaling.send({desc: pc.localDescription});
} else if (desc.type === 'answer') {
await pc.setRemoteDescription(desc);
} else {
console.log('Unsupported SDP type.');
}
} else if (candidate) {
await pc.addIceCandidate(candidate);
}
} catch (err) {
console.error(err);
}
};
للاطّلاع على عمليّات عرض/إجابة وتبادل المرشحين، يمكنك الاطّلاع على simpl.info RTCPeerConnection والاطّلاع على سجلّ وحدة التحكّم للحصول على مثال لمحادثة فيديو على صفحة واحدة. إذا أردت الحصول على مزيد من المعلومات، يمكنك تنزيل بيانات كاملة عن إشارات WebRTC وإحصاءاته من صفحة about://webrtc-internals في Google Chrome أو صفحة opera://webrtc-internals في Opera.
اكتشاف التطبيقات المشابهة
هذه طريقة رائعة لطرح السؤال "كيف يمكنني العثور على شخص للتحدّث إليه؟"
بالنسبة إلى المكالمات الهاتفية، تتوفّر لك أرقام هواتف ودلائل. لاستخدام ميزة الدردشة عبر الفيديو والمراسلة على الإنترنت، تحتاج إلى أنظمة إدارة الهوية والحضور، ووسيلة للمستخدمين لبدء الجلسات. تحتاج تطبيقات WebRTC إلى طريقة تتيح للعملاء إرسال إشارات إلى بعضهم البعض بأنّهم يريدون بدء مكالمة أو الانضمام إليها.
لا تحدِّد WebRTC آليات اكتشاف الأجهزة المشابهة، ولا يمكنك الاطّلاع على الخيارات هنا. يمكن أن تكون العملية بسيطة مثل إرسال عنوان URL عبر البريد الإلكتروني أو الرسائل. بالنسبة إلى تطبيقات محادثات الفيديو، مثل Talky وtawk.to وBrowser Meeting، يمكنك دعوة المستخدمين إلى مكالمة من خلال مشاركة رابط مخصّص. أنشأ المطوّر "كريس بال" تجربة webrtc بدون خادم مثيرة للاهتمام تتيح لمشاركي مكالمات WebRTC تبادل البيانات الوصفية من خلال أي خدمة مراسلة يفضّلونها، مثل المراسلة الفورية أو البريد الإلكتروني أو الحمام الزاجل.
كيف يمكنك إنشاء خدمة إرسال إشارات؟
للتذكير، لا تحدّد معايير WebRTC بروتوكولات وآليات الإرسال. مهما كان الخيار الذي تختاره، ستحتاج إلى خادم وسيط لتبادل رسائل الإشارات وبيانات التطبيقات بين العملاء. لا يمكن لتطبيق الويب أن يطلب من الإنترنت ببساطة "ربطي بصديقي".
لحسن الحظ، تكون رسائل الإشارات صغيرة ويتم تبادلها في معظم الأحيان في بداية المكالمة. في الاختبار الذي أجريناه باستخدام appr.tc لإجراء جلسة محادثة فيديو، تمّت معالجة ما يتراوح بين 30 و45 رسالة تقريبًا من خلال خدمة الإرسال، بإجمالي حجم لجميع الرسائل يبلغ 10 كيلوبايت تقريبًا.
بالإضافة إلى أنّها لا تتطلّب الكثير من النطاق الترددي، لا تستهلك خدمات إرسال الإشارات في WebRTC الكثير من المعالجة أو الذاكرة لأنّها لا تحتاج سوى إلى إعادة توجيه الرسائل والاحتفاظ بكمية صغيرة من بيانات حالة الجلسة، مثل العملاء المتصلين.
دفع الرسائل من الخادم إلى العميل
يجب أن تكون خدمة الرسائل لإصدار الإشارات ذات اتجاهين: من العميل إلى الخادم ومن الخادم إلى العميل. يخالف الاتصال الثنائي الاتجاه نموذج طلب/ردّ HTTP بين العميل والخادم، ولكن تم تطوير أساليب خداعية مختلفة، مثل الاستطلاع الطويل، على مدار سنوات عديدة من أجل دفع البيانات من خدمة تعمل على خادم ويب إلى تطبيق ويب يعمل في متصفّح.
وفي الآونة الأخيرة، تم تنفيذ واجهة برمجة التطبيقات EventSource
على نطاق واسع. ويؤدي ذلك إلى تفعيل الأحداث المُرسَلة من الخادم، وهي البيانات المُرسَلة من خادم ويب إلى برنامج متصفّح من خلال HTTP. تم تصميم EventSource
للمراسلة أحادية الاتجاه، ولكن يمكن استخدامه مع XHR لإنشاء خدمة لتبادل رسائل الإشارات. تُرسِل خدمة الإشارات رسالة من المتصل، يتم تسليمها من خلال طلب XHR، عن طريق دفعها من خلال EventSource
إلى المُتّصل به.
WebSocket هو حلّ أكثر ملاءمةً، وهو مصمّم للتواصل مزدوج الاتجاه بين العميل والخادم، أي الرسائل التي يمكن أن تتدفق في كلا الاتجاهين في الوقت نفسه. من مزايا خدمة الإشارات التي تم إنشاؤها باستخدام WebSocket أو الأحداث المُرسَلة من الخادم (EventSource
) أنّه يمكن تنفيذ الخلفية لواجهات برمجة التطبيقات هذه على مجموعة متنوعة من إطارات عمل الويب الشائعة لمعظم حِزم استضافة الويب للغات مثل PHP وPython وRuby.
تتوافق جميع المتصفّحات الحديثة مع WebSocket، باستثناء Opera Mini، والأهم من ذلك أنّ جميع المتصفّحات المتوافقة مع WebRTC تتوافق أيضًا مع WebSocket، سواء على أجهزة الكمبيوتر المكتبي أو الأجهزة الجوّالة. يجب استخدام TLS لجميع الاتصالات لضمان عدم اعتراض الرسائل غير المشفَّرة، وكذلك للحد من المشاكل المتعلّقة بالعبور عبر الخادم الوكيل. (لمزيد من المعلومات عن WebSocket وعبور الخادم الوكيل، اطّلِع على فصل WebRTC في مقالة High Performance Browser Networking (الشبكات عالية الأداء للمتصفّحات) التي كتبها "إيليا غريغوريك").
من الممكن أيضًا معالجة الإشارات من خلال جعل عملاء WebRTC يفحصون خادم المراسلة بشكل متكرّر من خلال Ajax، ولكنّ ذلك يؤدي إلى الكثير من طلبات الشبكة المتكرّرة، ما يشكّل مشكلة خاصة للأجهزة الجوّالة. حتى بعد إنشاء جلسة، يجب أن يطلب نداؤك رسائل الإشارات في حال حدوث تغييرات أو إنهاء الجلسة من قِبل نداءات أخرى. يستخدم مثال تطبيق WebRTC Book هذا الخيار مع بعض التحسينات على معدّل الاستطلاع.
إرسال الإشارات على نطاق واسع
على الرغم من أنّ خدمة الإشارات تستهلك قدرًا قليلاً نسبيًا من معدل نقل البيانات ووحدة المعالجة المركزية لكل عميل، قد يكون على خوادم الإشارات لتطبيق شائع معالجة الكثير من الرسائل الواردة من مواقع جغرافية مختلفة بمستويات عالية من الطلبات المتزامنة. تحتاج تطبيقات WebRTC التي تتلقّى عددًا كبيرًا من الزيارات إلى خوادم إشارات قادرة على معالجة عدد كبير من عمليات التحميل. لا نريد الخوض في التفاصيل هنا، ولكن هناك عدد من الخيارات للرسائل ذات الحجم الكبير والأداء العالي، بما في ذلك ما يلي:
بروتوكول المراسلة والتواجد القابل للتوسيع (XMPP)، المعروف في الأصل باسم Jabber، وهو بروتوكول تم تطويره للمراسلة الفورية ويمكن استخدامه للإرسال (تشمل عمليات تنفيذ الخادم ejabberd وOpenfire. تستخدم برامج JavaScript، مثل Strophe.js، BOSH لمحاكاة البث الثنائي الاتجاه، ولكن لأسباب مختلفة، قد لا يكون BOSH فعّالاً مثل WebSocket، وقد لا يتم توسيع نطاقه بشكل جيد للأسباب نفسها.) (يُرجى العِلم أنّ Jingle هو إضافة XMPP لتفعيل الصوت والفيديو. يستخدم مشروع WebRTC مكوّنات الشبكة والنقل من مكتبة libjingle، وهي عبارة عن تطبيق Jingle باستخدام لغة C++.)
مكتبات البرامج المفتوحة المصدر، مثل ZeroMQ (التي تستخدمها TokBox لخدمة Rumour) وOpenMQ (تطبّق NullMQ مفاهيم ZeroMQ على منصات الويب باستخدام بروتوكول STOMP عبر WebSocket)
منصات المراسلة التجارية المستندة إلى السحابة الإلكترونية التي تستخدم WebSocket (على الرغم من أنّها قد تلجأ إلى طلب البيانات بعد فترة طويلة)، مثل Pusher وKaazing وPubNub (تتوفّر لدى PubNub أيضًا واجهة برمجة تطبيقات لـ WebRTC).
منصات WebRTC التجارية، مثل vLine
(يقدّم دليل تكنولوجيات الويب في الوقت الفعلي الذي كتبه المطوّر "فيل ليغيتر" قائمة شاملة بخدمات المراسلة والمكتبات).
إنشاء خدمة إرسال إشارات باستخدام Socket.io على Node
في ما يلي رمز تطبيق ويب بسيط يستخدم خدمة إشارات تم إنشاؤها باستخدام Socket.io على Node. يسهّل تصميم Socket.io إنشاء خدمة لتبادل الرسائل، كما أنّ Socket.io ملائم بشكل خاص لإشارة WebRTC بسبب مفهوم الغرف المضمّن فيه. لم يتم تصميم هذا المثال للتمويه كخدمة إشارات من فئة الإنتاج، ولكنه سهل الفهم لعدد صغير نسبيًا من المستخدمين.
يستخدم Socket.io بروتوكول WebSocket مع خيارات احتياطية: طلب AJAX طويل المدى، وبث AJAX المتعدّد الأجزاء، وإطار Forever Iframe، وطلبات JSONP. وقد تم نقله إلى الخلفيات المختلفة، ولكن ربما يكون معروفًا أكثر بإصدار Node المستخدَم في هذا المثال.
لا يتضمّن هذا المثال WebRTC. تم تصميمه فقط لعرض كيفية إنشاء إشارات في تطبيق ويب. يمكنك الاطّلاع على سجلّ وحدة التحكّم لمعرفة ما يحدث عندما ينضم العملاء إلى غرفة ويتبادلون الرسائل. يقدّم الدرس التطبيقي حول الترميز لخدمة WebRTC هذا تعليمات مفصّلة حول كيفية دمج هذه الميزة في تطبيق متكامل مزوّد بخدمة WebRTC لإجراء محادثات فيديو.
في ما يلي العميل index.html
:
<!DOCTYPE html>
<html>
<head>
<title>WebRTC client</title>
</head>
<body>
<script src='/socket.io/socket.io.js'></script>
<script src='js/main.js'></script>
</body>
</html>
في ما يلي ملف JavaScript main.js
المُشار إليه في العميل:
const isInitiator;
room = prompt('Enter room name:');
const socket = io.connect();
if (room !== '') {
console.log('Joining room ' + room);
socket.emit('create or join', room);
}
socket.on('full', (room) => {
console.log('Room ' + room + ' is full');
});
socket.on('empty', (room) => {
isInitiator = true;
console.log('Room ' + room + ' is empty');
});
socket.on('join', (room) => {
console.log('Making request to join room ' + room);
console.log('You are the initiator!');
});
socket.on('log', (array) => {
console.log.apply(console, array);
});
في ما يلي تطبيق الخادم الكامل:
const static = require('node-static');
const http = require('http');
const file = new(static.Server)();
const app = http.createServer(function (req, res) {
file.serve(req, res);
}).listen(2013);
const io = require('socket.io').listen(app);
io.sockets.on('connection', (socket) => {
// Convenience function to log server messages to the client
function log(){
const array = ['>>> Message from server: '];
for (const i = 0; i < arguments.length; i++) {
array.push(arguments[i]);
}
socket.emit('log', array);
}
socket.on('message', (message) => {
log('Got message:', message);
// For a real app, would be room only (not broadcast)
socket.broadcast.emit('message', message);
});
socket.on('create or join', (room) => {
const numClients = io.sockets.clients(room).length;
log('Room ' + room + ' has ' + numClients + ' client(s)');
log('Request to create or join room ' + room);
if (numClients === 0){
socket.join(room);
socket.emit('created', room);
} else if (numClients === 1) {
io.sockets.in(room).emit('join', room);
socket.join(room);
socket.emit('joined', room);
} else { // max two clients
socket.emit('full', room);
}
socket.emit('emit(): client ' + socket.id +
' joined room ' + room);
socket.broadcast.emit('broadcast(): client ' + socket.id +
' joined room ' + room);
});
});
(لست بحاجة إلى التعرّف على node-static لتنفيذ ذلك. وقد تم استخدامها في هذا المثال.)
لتشغيل هذا التطبيق على المضيف المحلي، يجب تثبيت Node وSocket.IO وnode-static. يمكن تنزيل Node من Node.js (التثبيت سهل وسريع). لتثبيت Socket.IO وnode-static، يمكنك تشغيل أداة Node Package Manager من وحدة تحكّم في سطر الأوامر في دليل تطبيقك:
npm install socket.io
npm install node-static
لبدء الخادم، نفِّذ الأمر التالي من وحدة طرفية في دليل تطبيقك:
node server.js
من المتصفّح، افتح localhost:2013
. افتح علامة تبويب أو نافذة جديدة في أي متصفّح وافتح localhost:2013
مرة أخرى. للاطّلاع على ما يحدث، يُرجى التحقّق من وحدة التحكّم. في Chrome وOpera، يمكنك الوصول إلى وحدة التحكّم من خلال "أدوات مطوّري برامج Google Chrome" باستخدام Ctrl+Shift+J
(أو Command+Option+J
على أجهزة Mac).
بغض النظر عن النهج الذي تختاره للإرسال، يجب أن يوفّر تطبيقك الخلفية وتطبيق العميل على الأقل خدمات مشابهة لهذا المثال.
المشاكل المتعلّقة بإرسال الإشارات
- لن يبدأ
RTCPeerConnection
جمع المرشحين إلى أن يتم استدعاءsetLocalDescription()
. هذا مطلوب في مسودة JSEP IETF. - الاستفادة من ميزة "الرسائل القصيرة في وضع السكون" يُرجى الاتصال برقم
addIceCandidate()
فور وصول المرشحين.
خوادم الإشارة الجاهزة
إذا كنت لا تريد استخدام خادم خاص بك، تتوفّر عدة خوادم إشارات WebRTC، والتي تستخدم Socket.IO مثل المثال السابق ويتم دمجها مع مكتبات JavaScript الخاصة بخادم WebRTC:
- webRTC.io هي إحدى أوائل مكتبات التجريد لخدمة WebRTC.
- Signalmaster هو خادم إشارات تم إنشاؤه للاستخدام مع مكتبة برامج JavaScript SimpleWebRTC.
إذا كنت لا تريد كتابة أي رمز على الإطلاق، تتوفّر منصات WebRTC التجارية الكاملة من شركات مثل vLine وOpenTok وAsterisk.
في الواقع، أنشأت شركة Ericsson خادم إشارات باستخدام PHP على Apache في الأيام الأولى من WebRTC. وقد أصبح هذا الإجراء قديمًا إلى حدٍ ما، ولكن من المفيد الاطّلاع على الرمز البرمجي إذا كنت تفكر في إجراء مماثل.
أمان إرسال الإشارات
"الأمان هو فن عدم حدوث أي شيء".
سلمان رشدي
التشفير إلزامي لجميع مكوّنات WebRTC.
ومع ذلك، لا تحدّد معايير WebRTC آليات الإرسال، لذا عليك ضمان أمان الإرسال. إذا تمكّن المهاجم من الاستيلاء على الإشارات، يمكنه إيقاف الجلسات وإعادة توجيه الاتصالات وتسجيل المحتوى أو تغييره أو إدخاله.
إنّ أهم عامل في تأمين الإشارات هو استخدام بروتوكولات آمنة، مثل HTTPS وWSS (على سبيل المثال، بروتوكول أمان طبقة النقل)، والتي تضمن عدم إمكانية اعتراض الرسائل غير المشفَّرة. يجب أيضًا عدم بث رسائل الإشارات بطريقة يمكن للمتصلين الآخرين الوصول إليها باستخدام خادم الإشارات نفسه.
بعد إرسال الإشارات: استخدام ICE للتعامل مع جداول الترجمة وأجهزة جدار الحماية
بالنسبة إلى إرسال البيانات الوصفية، تستخدم تطبيقات WebRTC خادمًا وسيطًا، ولكن بالنسبة إلى بث الوسائط والبيانات الفعلي بعد إنشاء جلسة، تحاول RTCPeerConnection
ربط العملاء مباشرةً أو من نظير إلى نظير.
في السيناريو المثالي، سيكون لكل نقطة نهاية في WebRTC عنوان فريد يمكنها تبادله مع الأجهزة المشابهة الأخرى من أجل التواصل مباشرةً.
في الواقع، تعمل معظم الأجهزة خلف طبقة واحدة أو أكثر من NAT، وبعضها مزوّد ببرامج مكافحة فيروسات تحظر منافذ وبروتوكولات معيّنة، والعديد منها يعمل خلف الخوادم الوكيلة وجدران حماية الشركات. قد يتم تنفيذ جدار الحماية وNAT من خلال الجهاز نفسه، مثل جهاز توجيه WIFI في المنزل.
يمكن لتطبيقات WebRTC استخدام إطار عمل ICE للتغلب على تعقيدات الشبكات في العالم الواقعي. لكي يحدث ذلك، يجب أن يُرسل تطبيقك عناوين URL لخادم ICE إلى RTCPeerConnection
، كما هو موضّح في هذه المقالة.
يحاول بروتوكول ICE العثور على أفضل مسار لربط الأجهزة المتكافئة. ويعمل هذا الإجراء على تجربة جميع الاحتمالات بالتوازي واختيار الخيار الأكثر فعالية. يحاول بروتوكول ICE أولاً إجراء اتصال باستخدام عنوان المضيف الذي تم الحصول عليه من نظام التشغيل وشبكة الجهاز. وفي حال تعذّر ذلك (وهو ما سيحدث للأجهزة التي تعمل من خلال تكنولوجيا ترجمة عنوان الشبكة)، يحصل بروتوكول ICE على عنوان خارجي باستخدام خادم STUN، وفي حال تعذّر ذلك، يتم توجيه حركة المرور من خلال خادم إعادة توجيه TURN.
بعبارة أخرى، يتم استخدام خادم STUN للحصول على عنوان شبكة خارجي، ويتم استخدام خوادم TURN لنقل حركة البيانات في حال تعذّر الاتصال المباشر (من نظير إلى نظير).
يتوافق كل خادم TURN مع بروتوكول STUN. خادم TURN هو خادم STUN مزوّد بوظيفة إعادة توجيه مدمجة إضافية. يتعامل بروتوكول ICE أيضًا مع تعقيدات إعدادات NAT. في الواقع، قد تتطلّب عملية إنشاء ثغرة في ترجمة عنوان الشبكة أكثر من مجرد عنوان IP:port متاح للجميع.
يتم تحديد عناوين URL لخوادم STUN و/أو TURN (اختياريًا) من خلال تطبيق WebRTC في كائن الإعداد iceServers
الذي يمثّل الوسيطة الأولى لصانع RTCPeerConnection
. بالنسبة إلى appr.tc، تبدو هذه القيمة على النحو التالي:
{
'iceServers': [
{
'urls': 'stun:stun.l.google.com:19302'
},
{
'urls': 'turn:192.158.29.39:3478?transport=udp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
},
{
'urls': 'turn:192.158.29.39:3478?transport=tcp',
'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
'username': '28224511:1379330808'
}
]
}
بعد أن يحصل RTCPeerConnection
على هذه المعلومات، يتم تفعيل ميزة ICE تلقائيًا. يستخدم RTCPeerConnection
إطار عمل ICE لتحديد أفضل مسار بين الأجهزة المشابهة، ويعمل مع خوادم STUN وTURN حسب الحاجة.
STUN
توفّر آليات NAT جهازًا بعنوان IP لاستخدامه داخل شبكة محلية خاصة، ولكن لا يمكن استخدام هذا العنوان خارجيًا. بدون عنوان علني، لا يمكن لعناصر WebRTC التفاعل مع بعضها. لحلّ هذه المشكلة، يستخدم WebRTC بروتوكول STUN.
تعمل خوادم STUN على الإنترنت العام وتتولّى مهمة واحدة بسيطة، وهي التحقّق من عنوان IP:port للطلب الوافد (من تطبيق يعمل من خلال شبكة ترجمة عنوان الشبكة) وإرسال هذا العنوان مرة أخرى كاستجابة. بعبارة أخرى، يستخدم التطبيق خادم STUN لاكتشاف عنوان IP:المنفذ من منظور عام. تتيح هذه العملية لجهاز WebRTC الحصول على عنوان متاح للجميع ثم تمريره إلى جهاز آخر من خلال آلية إرسال الإشارات من أجل إعداد رابط مباشر. (في الممارسة العملية، تعمل تقنيات NAT المختلفة بطرق مختلفة وقد تكون هناك عدة طبقات من تقنية NAT، ولكن يبقى المبدأ نفسه ساريًا).
لا يحتاج خادم STUN إلى تنفيذ الكثير من الإجراءات أو تذكُّر الكثير من المعلومات، لذا يمكن لخوادم STUN ذات المواصفات المنخفضة نسبيًا معالجة عدد كبير من الطلبات.
تُجري معظم مكالمات WebRTC اتصالاً باستخدام بروتوكول STUN بنسبة% 86 وفقًا لموقع Webrtcstats.com، إلا أنّ هذا العدد قد يكون أقل للمكالمات بين الأجهزة المشابهة التي تعمل خلف جدران الحماية وإعدادات ترجمة عنوان الشبكة المعقدة.
TURN
يحاول RTCPeerConnection
إعداد اتصال مباشر بين الأجهزة المشابهة عبر بروتوكول UDP. إذا تعذّر ذلك، يلجأ RTCPeerConnection
إلى بروتوكول TCP. وفي حال تعذّر ذلك، يمكن استخدام خوادم TURN كخيار احتياطي لنقل البيانات بين نقاط النهاية.
للتذكير فقط، يُستخدَم بروتوكول TURN لنقل الصوت والفيديو وبث البيانات بين الأجهزة المشابهة، وليس لتوجيه البيانات.
تحتوي خوادم TURN على عناوين عامة، لذا يمكن للأجهزة المشابهة التواصل معها حتى إذا كانت الأجهزة المشابهة خلف جدران حماية أو خوادم وكيلة. تتمثل مهمة خوادم TURN في إعادة توجيه البث، وهي مهمة بسيطة من الناحية النظرية. ومع ذلك، على عكس خوادم STUN، تستهلك هذه الخوادم بشكلٍ أساسي قدرًا كبيرًا من معدل نقل البيانات. بعبارة أخرى، يجب أن تكون خوادم TURN أكثر فعالية.
يوضّح هذا المخطّط البياني آلية عمل ميزة "الاستدارة". لم ينجح بروتوكول STUN، لذا يلجأ كل جهاز إلى استخدام خادم TURN.
نشر خوادم STUN وTURN
لأغراض الاختبار، تشغّل Google خادم STUN متاحًا للجميع، وهو stun.l.google.com:19302، كما يستخدمه appr.tc. لخدمة STUN/TURN في مرحلة الإنتاج، استخدِم rfc5766-turn-server. يتوفّر رمز المصدر لخادمَي STUN وTURN على GitHub، حيث يمكنك أيضًا العثور على روابط تؤدي إلى عدة مصادر للمعلومات حول تثبيت الخادم. تتوفّر أيضًا صورة لجهاز افتراضي في Amazon Web Services.
خادم TURN بديل هو restund، وهو متاح كـ رمز مصدر ومتاح أيضًا لخدمة AWS. في ما يلي تعليمات حول كيفية إعداد restund على Compute Engine.
- افتح جدار الحماية حسب الحاجة لبروتوكول tcp=443 وudp/tcp=3478.
- أنشئ أربع نُسخ، واحدة لكل عنوان IP علني، باستخدام صورة Ubuntu 12.06 العادية.
- إعداد إعدادات جدار الحماية المحلي (السماح لأي جهاز من أي جهاز)
- أدوات التثبيت:
shell sudo apt-get install make sudo apt-get install gcc
- ثبِّت Libre من creytiv.com/re.html.
- يمكنك الحصول على restund من creytiv.com/restund.html وفك ضغطه./
wget
hancke.name/restund-auth.patch وطبِّقpatch -p1 < restund-auth.patch
.- شغِّل
make
وsudo make install
لتطبيق libre وrestund. - عدِّل
restund.conf
وفقًا لاحتياجاتك (استبدِل عناوين IP وتأكَّد من أنّها تحتوي على السر المشترَك نفسه) وانسخها إلى/etc
. - انسخ
restund/etc/restund
إلى/etc/init.d/
. - ضبط restund:
- اضبط
LD_LIBRARY_PATH
. - انسخ
restund.conf
إلى/etc/restund.conf
. - اضبط
restund.conf
لاستخدام 10 الصحيح. عنوان IP
- اضبط
- تشغيل restund
- اختبار استخدام برنامج تشغيل الاختبار من جهاز بعيد:
./client IP:port
مزيد من الإمكانيات غير المخصّصة للمحادثات بين شخصين: WebRTC المتعدّد الأطراف
يمكنك أيضًا الاطّلاع على معيار IETF المقترَح من Justin Uberti لـ واجهة برمجة تطبيقات REST للوصول إلى خدمات TURN.
من السهل تخيل حالات استخدام لبث الوسائط تتجاوز مكالمة بسيطة بين شخصين. على سبيل المثال، مكالمات الفيديو بين مجموعة من الزملاء أو حدث مفتوح يضم متحدثًا واحدًا ومئات أو ملايين المشاهدين.
يمكن لتطبيق WebRTC استخدام عدة RTCPeerConnections حتى تتصل كل نقطة نهاية بجميع نقاط النهاية الأخرى في عملية ضبط الشبكة. هذا هو النهج الذي تتّبعه التطبيقات، مثل talky.io، وهو يعمل بشكل جيد بشكل ملحوظ لعدد صغير من التطبيقات المشابهة. وبعد ذلك، يصبح استهلاك المعالجة وسعة النطاق الزائد، خاصةً لعملاء الأجهزة الجوّالة.
بدلاً من ذلك، يمكن لتطبيق WebRTC اختيار نقطة نهاية واحدة لتوزيع أحداث البث على جميع التطبيقات الأخرى في تكوين نجمي. من الممكن أيضًا تشغيل نقطة نهاية WebRTC على خادم وإنشاء آلية إعادة التوزيع الخاصة بك (يوفّر موقع webrtc.org نموذجًا لتطبيق العميل).
منذ إصدار Chrome 31 وOpera 18، يمكن استخدام MediaStream
من RTCPeerConnection
كإدخال لآخر. ويمكن أن يؤدي ذلك إلى توفير تصاميم أكثر مرونة لأنّه يتيح لتطبيق الويب معالجة توجيه المكالمات من خلال اختيار نظير آخر للاتصال به. للاطّلاع على كيفية تنفيذ ذلك، يمكنك الاطّلاع على عيّنات WebRTC لإعادة توجيه الاتصال بين الأجهزة المشابهة وعيّنات WebRTC لاتصالات متعدّدة بين الأجهزة المشابهة.
وحدة التحكّم في الاتصال المتعدّد النقاط
إنّ استخدام وحدة التحكّم المتعدّد (MCU) هو خيار أفضل لعدد كبير من نقاط النهاية. هذا خادم يعمل كجسر لتوزيع الوسائط بين عدد كبير من المشاركين. يمكن لوحدات التحكّم في حدود الجلسة التعامل مع درجات الدقة وبرامج الترميز ومعدّلات عرض اللقطات المختلفة في مؤتمر الفيديو، ومعالجة تحويل الترميز، وإعادة توجيه البث بشكل انتقائي، ومزج الصوت والفيديو أو تسجيلهما. بالنسبة إلى المكالمات بين أطراف متعددة، هناك عدد من المشاكل التي يجب أخذها في الاعتبار، لا سيما كيفية عرض مصادر فيديو متعددة ومزج الصوت من مصادر متعددة. تحاول منصات السحابة الإلكترونية، مثل vLine، أيضًا تحسين توجيه الزيارات.
من الممكن شراء حزمة أجهزة MCU كاملة أو إنشاء حزمة خاصة بك.
تتوفّر عدة خيارات لبرامج MCU مفتوحة المصدر. على سبيل المثال، تُنتج شركة Licode (المعروفة سابقًا باسم Lynckia) وحدة تحكم في حدود الجلسة مفتوحة المصدر لخدمة WebRTC. يتضمّن OpenTok Mantis.
خارج نطاق المتصفّحات: خدمات نقل الصوت عبر بروتوكول الإنترنت والهواتف والمراسلة
تسمح الطبيعة الموحدة لبروتوكول WebRTC بإنشاء اتصال بين تطبيق WebRTC الذي يعمل في متصفّح وجهاز أو منصة تعمل على منصة تواصل أخرى، مثل هاتف أو نظام مكالمات فيديو.
بروتوكول SIP هو بروتوكول إشارات تستخدمه أنظمة الصوت على الإنترنت (VoIP) وأنظمة اجتماعات الفيديو. لتفعيل الاتصال بين تطبيق ويب WebRTC وعميل SIP، مثل نظام اجتماعات الفيديو، يحتاج WebRTC إلى خادم وكيل للتوسّط في الإشارات. يجب أن يتدفق الإرسال عبر البوابة، ولكن بعد بدء الاتصال، يمكن أن تتدفق حركة SRTP (الفيديو والصوت) مباشرةً من جهاز إلى آخر.
الشبكة العامة لتحويل الهاتف (PSTN) هي شبكة مُدارة عبر شبكة دائرية لجميع الهواتف التناظرية القديمة. بالنسبة إلى المكالمات بين تطبيقات الويب WebRTC والهواتف، يجب أن تمرّ حركة البيانات عبر بوابة PSTN. وبالمثل، تحتاج تطبيقات الويب التي تستخدم WebRTC إلى خادم XMPP وسيط للتواصل مع نقاط نهاية Jingle، مثل برامج المراسلة الفورية. طوّرت Google بروتوكول Jingle كإضافة إلى بروتوكول XMPP لتفعيل الصوت والفيديو في خدمات المراسلة. تستند عمليات تنفيذ WebRTC الحالية إلى مكتبة libjingle لبرنامج C++، وهي عملية تنفيذ لبرنامج Jingle تم تطويرها في البداية لتطبيق Talk.
يستفيد عدد من التطبيقات والمكتبات والمنصات من قدرة WebRTC على التواصل مع العالم الخارجي:
- sipML5: برنامج SIP مفتوح المصدر مكتوب بلغة JavaScript
- jsSIP: مكتبة JavaScript SIP
- Phono: واجهة برمجة تطبيقات JavaScript مفتوحة المصدر للهاتف تم إنشاؤها كمكوّن إضافي
- Zingaya: تطبيق مصغّر قابل للتضمين على الهاتف
- Twilio: الصوت والمراسلة
- Uberconference: مكالمات الفيديو
أنشأ مطوّرو sipML5 أيضًا بوابة webrtc2sip. عرضت شركتا Tethr وTropo إطار عمل للتواصل في حالات الكوارث "في حقيبة يد" باستخدام خلية OpenBTS لإتاحة الاتصالات بين الهواتف العادية وأجهزة الكمبيوتر من خلال WebRTC. هذا يعني أنّه يتم إجراء اتصال هاتفي بدون مشغّل شبكة الجوّال.
التعرف على المزيد
يوفّر الدرس التطبيقي حول WebRTC تعليمات خطوة بخطوة حول كيفية إنشاء تطبيق محادثات فيديو ونصوص باستخدام خدمة إشارات Socket.io التي تعمل على Node.
عرض WebRTC في Google I/O لعام 2013 مع رئيس فريق التكنولوجيا في WebRTC، جاستين أوبيرتي
عرض SFHTML5 الذي قدمه "كريس ويلسون": مقدمة عن تطبيقات WebRTC
يقدّم الكتاب الذي يتألف من 350 صفحة بعنوان WebRTC: واجهات برمجة التطبيقات وبروتوكولات RTCWEB لتطبيقات HTML5 في الوقت الفعلي على الويب الكثير من التفاصيل حول مسارات البيانات والإشارات، ويتضمن عددًا من المخططات البيانية التفصيلية لتخطيط الشبكة.
WebRTC وSignaling: ما تعلمناه خلال عامَين: مشاركة مدوّنة TokBox حول سبب اعتبار عدم تضمين Signaling في المواصفات فكرة جيدة
يقدّم الدليل العملي لبناء تطبيقات WebRTC الذي كتبه بن سترونغ الكثير من المعلومات حول طوبولوجيات WebRTC وبنيتها الأساسية.
يتناول فصل WebRTC في كتاب Ilya Grigorik High Performance Browser Networking بالتفصيل بنية WebRTC وحالات الاستخدام والأداء.