Benzerler arasında bağlantıları kullanmaya başlama

Eş bağlantıları, WebRTC spesifikasyonlarının, eşler arası protokol kullanarak iletişim kurmak için farklı bilgisayarlardaki iki uygulamayı bağlamayla ilgili olan kısmıdır. Eşler arasındaki iletişim video, ses veya rastgele ikili veri olabilir (RTCDataChannel API'yi destekleyen istemciler için). İki eşin nasıl bağlanabileceğini bulmak için her iki istemcinin de bir ICE sunucusu yapılandırması sağlaması gerekir. Bu, bir STUN veya TURN sunucusu olup her istemciye ICE adayı sağlamakla görevlidir. Bu adaylar daha sonra uzak eşe aktarılır. ICE adaylarının aktarılmasına genellikle sinyal verme adı verilir.

Sinyal

WebRTC spesifikasyonu, ICE (Internet Bağlantısı Kurma) sunucusuyla iletişim kurmak için API'ler içerir ancak sinyal bileşeni bu spesifikasyonun bir parçası değildir. İki eşin nasıl bağlanacağını paylaşabilmesi için sinyal gönderme gerekir. Bu sorun genellikle, web uygulamalarının eş bağlantısı başlatılmadan önce gerekli bilgileri aktarabileceği normal bir HTTP tabanlı Web API'si (ör. REST hizmeti veya başka bir RPC mekanizması) aracılığıyla çözülür.

Aşağıdaki kod snippet'inde, bu hayali sinyal hizmetini mesajları eşzamansız olarak göndermek ve almak için nasıl kullanabileceğiniz gösterilmektedir. Bu, bu kılavuzun geri kalanındaki örneklerde gerektiğinde kullanılacaktır.

// 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!');

İşaretleme birçok farklı şekilde uygulanabilir ve WebRTC spesifikasyonu belirli bir çözümü tercih etmez.

Eş bağlantıları başlatma

Her eş bağlantısı bir RTCPeerConnection nesnesi tarafından yönetilir. Bu sınıfın kurucusu, parametresi olarak tek bir RTCConfiguration nesnesi alır. Bu nesne, eş bağlantısının nasıl ayarlandığını tanımlar ve kullanılacak ICE sunucuları hakkında bilgi içermelidir.

RTCPeerConnection oluşturulduktan sonra, arayan eş mi yoksa alıcı eş mi olduğumuza bağlı olarak bir SDP teklifi veya yanıtı oluşturmamız gerekir. SDP teklifi veya yanıtı oluşturulduktan sonra farklı bir kanal üzerinden uzak eşe gönderilmelidir. SDP nesnelerinin uzak eşlere iletilmesine sinyal verme denir ve bu işlem WebRTC spesifikasyonu kapsamında değildir.

Arama yapan taraftan eş bağlantısı kurulumunu başlatmak için bir RTCPeerConnection nesnesi oluştururuz ve ardından createOffer()'yi çağırarak bir RTCSessionDescription nesnesi oluştururuz. Bu oturum açıklaması, setLocalDescription() kullanılarak yerel açıklama olarak ayarlanır ve ardından sinyal kanalımız üzerinden alıcı tarafa gönderilir. Ayrıca, sunulan oturum açıklamamıza yanıtın alıcı taraftan alınması durumunda sinyal kanalımıza bir dinleyici de ayarlarız.

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});
}

Alıcı tarafta, RTCPeerConnection örneğimizi oluşturmadan önce gelen bir teklif bekleriz. Bu işlem tamamlandıktan sonra, setRemoteDescription() kullanarak alınan teklifi ayarlarız. Ardından, alınan teklife yanıt oluşturmak için createAnswer() işlevini çağırırız. Bu yanıt, setLocalDescription() kullanılarak yerel açıklama olarak ayarlanır ve ardından sinyal sunucumuz üzerinden arayan tarafa gönderilir.

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});
    }
});

İki eş, hem yerel hem de uzak oturum açıklamalarını ayarladıktan sonra uzak eşin özelliklerini bilir. Bu, eşler arasındaki bağlantının hazır olduğu anlamına gelmez. Bunun çalışması için her eşlenikteki ICE adaylarını toplayıp diğer eşleniği (sinyal kanalıyla) aktarmamız gerekir.

ICE adayları

İki eş, WebRTC kullanarak iletişim kurabilmek için bağlantı bilgilerini paylaşmalıdır. Ağ koşulları çeşitli faktörlere bağlı olarak değişebileceğinden, genellikle bir eşe bağlanabilecek olası adayları bulmak için harici bir hizmet kullanılır. Bu hizmete ICE adı verilir ve STUN veya TURN sunucusu kullanılır. STUN, NAT için Oturum Geçiş Araçları anlamına gelir ve genellikle çoğu WebRTC uygulamasında dolaylı olarak kullanılır.

TURN (Geçiş NAT'i Kullanarak Geçiş), STUN protokollerini içeren daha gelişmiş bir çözümdür ve ticari WebRTC tabanlı hizmetlerin çoğu, eşler arasında bağlantı kurmak için bir TURN sunucusu kullanır. WebRTC API, hem STUN hem de TURN'i doğrudan destekler ve daha kapsamlı bir terim olan Internet Connectivity Establishment (İnternet Bağlantısı Kurma) altında toplanır. WebRTC bağlantısı oluştururken genellikle RTCPeerConnection nesnesinin yapılandırmasında bir veya daha fazla ICE sunucusu sağlarız.

Damla ICE

Bir RTCPeerConnection nesnesi oluşturulduktan sonra temel çerçeve, bağlantı kurma adayları (ICE adayları) toplamak için sağlanan ICE sunucularını kullanır. RTCPeerConnection tarihindeki icegatheringstatechange etkinliği, ICE toplantısının hangi durumda olduğunu (new, gathering veya complete) gösterir.

Bir eşin ICE toplama işleminin tamamlanmasını beklemesi mümkün olsa da genellikle "damla ICE" tekniği kullanmak ve her ICE adayını keşfedildikten sonra uzaktaki eşe iletmek çok daha verimlidir. Bu, eş bağlantının kurulum süresini önemli ölçüde azaltır ve video görüşmesinin daha az gecikmeyle başlatılmasına olanak tanır.

ICE adaylarını toplamak için icecandidate etkinliği için bir dinleyici eklemeniz yeterlidir. Bu dinleyicide yayınlanan RTCPeerConnectionIceEvent, uzak eşe gönderilmesi gereken yeni bir adayı temsil eden candidate mülkünü içerir (Sinyal gönderme bölümüne bakın).

// 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);
        }
    }
});

Bağlantı kuruldu

ICE adayları alındıktan sonra, eş bağlantımızın durumunun bağlı olarak değişmesini bekleyebiliriz. Bunu algılamak için RTCPeerConnection etkinliğimizi dinleyeceğimiz bir dinleyici connectionstatechange ekliyoruz.

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

RTCPeerConnection API dokümanları