मिलते-जुलते ऐप्लिकेशन के साथ शुरुआत करना

पीयर कनेक्शन, WebRTC की खास बातों का हिस्सा है. यह अलग-अलग कंप्यूटर पर दो ऐप्लिकेशन को कनेक्ट करने के लिए काम करता है, ताकि पीयर-टू-पीयर प्रोटोकॉल का इस्तेमाल करके कम्यूनिकेट किया जा सके. पीयर के बीच वीडियो, ऑडियो या मनमुताबिक बाइनरी डेटा (RTCDataChannel एपीआई के साथ काम करने वाले क्लाइंट के लिए) का इस्तेमाल करके कम्यूनिकेट किया जा सकता है. दो पीयर के कनेक्ट होने का तरीका जानने के लिए, दोनों क्लाइंट को आईसीई सर्वर कॉन्फ़िगरेशन देना होगा. यह STUN या TURN-सर्वर होता है. इसकी भूमिका, हर क्लाइंट को आईसीई उम्मीदवार उपलब्ध कराना होती है. इसके बाद, इन उम्मीदवारों को रिमोट पीयर को ट्रांसफ़र कर दिया जाता है. आईसीई उम्मीदवारों को ट्रांसफ़र करने की प्रोसेस को आम तौर पर सिग्नल भेजना कहा जाता है.

सिग्नलिंग

WebRTC स्पेसिफ़िकेशन में, आईसीई (इंटरनेट कनेक्टिविटी सेटअप) सर्वर के साथ कम्यूनिकेट करने के लिए एपीआई शामिल हैं. हालांकि, सिग्नल भेजने और पाने वाला कॉम्पोनेंट इसका हिस्सा नहीं है. सिग्नल भेजने की ज़रूरत इसलिए होती है, ताकि दो पीयर यह शेयर कर सकें कि उन्हें कैसे कनेक्ट करना चाहिए. आम तौर पर, इसे सामान्य एचटीटीपी पर आधारित वेब एपीआई (जैसे, कोई 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 बन जाने के बाद, हमें एसडीपी ऑफ़र या जवाब बनाना होगा. यह इस बात पर निर्भर करता है कि हम कॉल करने वाले हैं या कॉल पाने वाले. एसडीपी ऑफ़र या जवाब बनाने के बाद, उसे किसी दूसरे चैनल के ज़रिए रिमोट पीयर को भेजा जाना चाहिए. रिमोट पीयर को एसडीपी ऑब्जेक्ट भेजने को सिग्नल भेजना कहा जाता है. इसे WebRTC स्पेसिफ़िकेशन में शामिल नहीं किया गया है.

कॉल करने वाले पक्ष से पीयर कनेक्शन सेटअप शुरू करने के लिए, हम एक RTCPeerConnection ऑब्जेक्ट बनाते हैं. इसके बाद, RTCSessionDescription ऑब्जेक्ट बनाने के लिए createOffer() को कॉल करते हैं. इस सेशन के ब्यौरे को 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 के उम्मीदवार

दो पीयर, WebRTC का इस्तेमाल करके आपस में बातचीत करने से पहले, एक-दूसरे के साथ इंटरनेट कनेक्शन की जानकारी शेयर करते हैं. नेटवर्क की स्थिति कई बातों के आधार पर अलग-अलग हो सकती है. इसलिए, आम तौर पर किसी पीयर से कनेक्ट करने के लिए, संभावित उम्मीदवारों का पता लगाने के लिए किसी बाहरी सेवा का इस्तेमाल किया जाता है. इस सेवा को आईसीई कहा जाता है. इसमें STUN या TURN सर्वर का इस्तेमाल किया जाता है. STUN का मतलब है, NAT के लिए सेशन ट्रैवल यूटिलिटी. आम तौर पर, ज़्यादातर WebRTC ऐप्लिकेशन में इसका इस्तेमाल सीधे तौर पर नहीं किया जाता.

TURN (ट्रैवर्सल यूज़िंग रिले एनएटी), एक बेहतर समाधान है. इसमें STUN प्रोटोकॉल शामिल होते हैं. साथ ही, ज़्यादातर व्यावसायिक WebRTC सेवाएं, पीयर के बीच कनेक्शन बनाने के लिए TURN सर्वर का इस्तेमाल करती हैं. WebRTC API, STUN और TURN, दोनों के साथ सीधे तौर पर काम करता है. इसे इंटरनेट कनेक्टिविटी इस्टैब्लिशमेंट के ज़्यादा सटीक शब्द के तहत इकट्ठा किया जाता है. WebRTC कनेक्शन बनाते समय, हम आम तौर पर RTCPeerConnection ऑब्जेक्ट के कॉन्फ़िगरेशन में एक या एक से ज़्यादा आईसीई सर्वर उपलब्ध कराते हैं.

Trickle ICE

RTCPeerConnection ऑब्जेक्ट बन जाने के बाद, मौजूदा फ़्रेमवर्क, दिए गए आईसीई सर्वर का इस्तेमाल करके, कनेक्शन बनाने के लिए उम्मीदवारों (आईसीई उम्मीदवारों) को इकट्ठा करता है. RTCPeerConnection पर मौजूद इवेंट icegatheringstatechange से पता चलता है कि आईसीई इकट्ठा करने की प्रोसेस किस स्टेटस में है (new, gathering या complete).

हालांकि, किसी पीयर के लिए आईसीई इकट्ठा होने तक इंतज़ार करना मुमकिन है, लेकिन आम तौर पर "ट्रिकल आईसीई" तकनीक का इस्तेमाल करना और हर आईसीई उम्मीदवार को रिमोट पीयर को भेजना ज़्यादा असरदार होता है. इससे, पीयर कनेक्टिविटी के सेटअप में लगने वाला समय काफ़ी कम हो जाएगा. साथ ही, वीडियो कॉल में कम देरी होगी.

आईसीई उम्मीदवारों को इकट्ठा करने के लिए, बस 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);
        }
    }
});

कनेक्शन स्थापित

आईसीई उम्मीदवार मिलने के बाद, हमें उम्मीद करनी चाहिए कि हमारे पीयर कनेक्शन की स्थिति, कनेक्टेड स्टेटस में बदल जाएगी. इसकी पहचान करने के लिए, हम अपने RTCPeerConnection में एक लिसनर जोड़ते हैं, जहां हम connectionstatechange इवेंट को सुनते हैं.

// Listen for connectionstatechange on the local RTCPeerConnection
peerConnection.addEventListener('connectionstatechange', event => {
    if (peerConnection.connectionState === 'connected') {
        // Peers connected!
    }
});

RTCPeerConnection API का दस्तावेज़