পিয়ার কানেকশন হল WebRTC স্পেসিফিকেশনের একটি অংশ যা পিয়ার-টু-পিয়ার প্রোটোকল ব্যবহার করে যোগাযোগের জন্য বিভিন্ন কম্পিউটারে দুটি অ্যাপ্লিকেশনকে সংযুক্ত করার বিষয়ে কাজ করে। সহকর্মীদের মধ্যে যোগাযোগ ভিডিও, অডিও বা নির্বিচারে বাইনারি ডেটা হতে পারে ( RTCDataChannel
API সমর্থনকারী ক্লায়েন্টদের জন্য)। কিভাবে দুই সহকর্মী সংযোগ করতে পারে তা আবিষ্কার করার জন্য, উভয় ক্লায়েন্টকে একটি ICE সার্ভার কনফিগারেশন প্রদান করতে হবে। এটি হয় একটি STUN বা একটি টার্ন-সার্ভার, এবং তাদের ভূমিকা হল প্রতিটি ক্লায়েন্টকে ICE প্রার্থী প্রদান করা যা তারপরে দূরবর্তী পিয়ারে স্থানান্তরিত হয়। ICE প্রার্থীদের এই স্থানান্তরকে সাধারণত সিগন্যালিং বলা হয়।
সংকেত
WebRTC স্পেসিফিকেশন একটি ICE (ইন্টারনেট কানেক্টিভিটি এস্টাব্লিশমেন্ট) সার্ভারের সাথে যোগাযোগের জন্য APIs অন্তর্ভুক্ত করে, কিন্তু সিগন্যালিং উপাদান এটির অংশ নয়। দুই সমবয়সীদের কীভাবে সংযোগ করা উচিত তা শেয়ার করার জন্য সিগন্যালিং প্রয়োজন। সাধারণত এটি একটি নিয়মিত HTTP-ভিত্তিক ওয়েব API (যেমন, একটি REST পরিষেবা বা অন্যান্য RPC প্রক্রিয়া) এর মাধ্যমে সমাধান করা হয় যেখানে ওয়েব অ্যাপ্লিকেশনগুলি পিয়ার সংযোগ শুরু করার আগে প্রয়োজনীয় তথ্য রিলে করতে পারে।
ফলো কোড স্নিপেট দেখায় কিভাবে এই কাল্পনিক সিগন্যালিং পরিষেবাটি অ্যাসিঙ্ক্রোনাসভাবে বার্তা পাঠাতে এবং গ্রহণ করতে ব্যবহার করা যেতে পারে। প্রয়োজনে এই নির্দেশিকায় অবশিষ্ট উদাহরণে এটি ব্যবহার করা হবে।
// 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
অবজেক্ট তৈরি করি এবং তারপর 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});
}
});
একবার দুই সহকর্মী স্থানীয় এবং দূরবর্তী উভয় সেশনের বিবরণ সেট করলে তারা দূরবর্তী সমবয়সীর ক্ষমতাগুলি জানে। এর মানে এই নয় যে সমবয়সীদের মধ্যে সংযোগ প্রস্তুত। এটি কাজ করার জন্য আমাদের প্রতিটি পিয়ারে আইসিই প্রার্থীদের সংগ্রহ করতে হবে এবং অন্য পিয়ারে (সিগন্যালিং চ্যানেলের উপরে) স্থানান্তর করতে হবে।
আইসিই প্রার্থীরা
WebRTC ব্যবহার করে দুজন সহকর্মী যোগাযোগ করার আগে, তাদের সংযোগের তথ্য বিনিময় করতে হবে। যেহেতু নেটওয়ার্কের অবস্থা বিভিন্ন কারণের উপর নির্ভর করে পরিবর্তিত হতে পারে, একটি বহিরাগত পরিষেবা সাধারণত একজন সহকর্মীর সাথে সংযোগ করার জন্য সম্ভাব্য প্রার্থীদের আবিষ্কারের জন্য ব্যবহার করা হয়। এই পরিষেবাটিকে ICE বলা হয় এবং এটি একটি STUN বা একটি টার্ন সার্ভার ব্যবহার করছে৷ STUN মানে NAT-এর জন্য সেশন ট্রাভার্সাল ইউটিলিটি, এবং সাধারণত বেশিরভাগ WebRTC অ্যাপ্লিকেশনে পরোক্ষভাবে ব্যবহৃত হয়।
টার্ন (Traversal Using Relay NAT) হল আরও উন্নত সমাধান যা STUN প্রোটোকলগুলিকে অন্তর্ভুক্ত করে এবং বেশিরভাগ বাণিজ্যিক WebRTC ভিত্তিক পরিষেবাগুলি সহকর্মীদের মধ্যে সংযোগ স্থাপনের জন্য একটি টার্ন সার্ভার ব্যবহার করে৷ WebRTC API সরাসরি STUN এবং TURN উভয়কেই সমর্থন করে এবং এটি আরও সম্পূর্ণ শব্দ ইন্টারনেট সংযোগ স্থাপনের অধীনে সংগ্রহ করা হয়। একটি WebRTC সংযোগ তৈরি করার সময়, আমরা সাধারণত RTCPeerConnection
অবজেক্টের কনফিগারেশনে এক বা একাধিক ICE সার্ভার প্রদান করি।
ট্রিকল আইসিই
একবার একটি RTCPeerConnection
অবজেক্ট তৈরি হয়ে গেলে, অন্তর্নিহিত ফ্রেমওয়ার্ক প্রদত্ত আইসিই সার্ভার ব্যবহার করে কানেক্টিভিটি প্রতিষ্ঠার (আইসিই প্রার্থীদের) প্রার্থীদের সংগ্রহ করতে। RTCPeerConnection
এ ইভেন্ট icegatheringstatechange
ইভেন্টটি ICE সমাবেশ কোন অবস্থায় রয়েছে তা নির্দেশ করে ( new
, gathering
বা complete
)।
যদিও একজন সমবয়সীর পক্ষে 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!
}
});