WebRTC veri kanallarıyla tarayıcılar arasında veri gönderme

İletişim, oyun veya dosya aktarımı için iki tarayıcı arasında veri göndermek oldukça karmaşık bir süreç olabilir. Verileri aktarmak için bir sunucu kurup ödeme yapmayı ve bunu birden fazla veri merkezine ölçeklendirmeyi gerektirir. Bu senaryoda yüksek gecikme süresi yaşanabilir ve verilerin gizliliğini korumak zorlaşır.

Bu sorunlar, verileri doğrudan bir eşten diğerine aktarmak için WebRTC'nin RTCDataChannel API'si kullanılarak hafifletilebilir. Bu makalede, veri kanallarının nasıl ayarlanacağı ve kullanılacağı ile ilgili temel bilgilerin yanı sıra günümüzde web'de sık karşılaşılan kullanım alanları ele alınmaktadır.

Neden başka bir veri kanalı?

WebSocket, AJAX ve Server Sent Events'i destekliyoruz. Neden başka bir iletişim kanalına ihtiyacımız var? WebSocket çift yönlüdür ancak bu teknolojilerin tümü bir sunucuya veya sunucudan iletişim için tasarlanmıştır.

RTCDataChannel farklı bir yaklaşım benimser:

  • Bu özellik, eşler arası bağlantı sağlayan RTCPeerConnection API'siyle çalışır. Bu durum, gecikmenin azalmasına (ara sunucu yok ve daha az "atlama") neden olabilir.
  • RTCDataChannel, Akış Kontrolü İletim Protokolü'nü (SCTP) kullanır. Bu protokol, yapılandırılabilir teslimat semantiğine (sıra dışı teslimat ve yeniden iletim yapılandırması) olanak tanır.

RTCDataChannel, Google Chrome, Opera ve Firefox'ta masaüstü ve Android'de SCTP desteğiyle kullanılabilir.

Uyarı: Sinyal, STUN ve TURN

WebRTC, eşler arası iletişime olanak tanır ancak eş bağlantısı başlatmak için medya ve ağ meta verilerini değiştirmek üzere sinyal için sunuculara ihtiyaç duyar.

WebRTC, NAT'ler ve güvenlik duvarlarıyla şu şekilde başa çıkar:

  • Eşler arasında mümkün olan en iyi ağ yolunu oluşturmak için ICE çerçevesi.
  • Her eş için herkese açık olarak erişilebilen bir IP ve bağlantı noktası belirlemek üzere STUN sunucuları.
  • Doğrudan bağlantı başarısız olursa ve veri aktarımı gerekirse TURN sunucuları.

WebRTC'nin sinyal ve ağ oluşturma için sunucularla nasıl çalıştığı hakkında daha fazla bilgi edinmek için WebRTC in the real world: STUN, TURN, and signaling (Gerçek dünyada WebRTC: STUN, TURN ve sinyal) başlıklı makaleyi inceleyin.

Özellikler

RTCDataChannel API, esnek bir veri türleri grubunu destekler. API, WebSocket'i tam olarak taklit edecek şekilde tasarlanmıştır ve RTCDataChannel, dizelerin yanı sıra JavaScript'teki bazı ikili türleri (ör. Blob, ArrayBuffer ve ArrayBufferView) destekler. Bu türler, dosya aktarımı ve çok oyunculu oyunlarla çalışırken faydalı olabilir.

RTCDataChannel; güvenilir olmayan ve sıralanmamış modda (Kullanıcı Datagram Protokolü veya UDP'ye benzer), güvenilir ve sıralanmış modda (İletim Kontrol Protokolü veya TCP'ye benzer) ve kısmen güvenilir modlarda çalışabilir:

  • Güvenilir ve sıralı mod, iletilerin iletilmesini ve teslim edilme sırasını garanti eder. Bu işlem ek yük getirir ve bu nedenle bu modun daha yavaş çalışmasına neden olabilir.
  • Güvenilir olmayan ve sırasız mod, her iletinin diğer tarafa ulaşacağını veya hangi sırayla ulaşacağını garanti etmez. Bu sayede ek yük ortadan kalkar ve mod çok daha hızlı çalışır.
  • Kısmi güvenilir mod, iletinin yeniden iletim zaman aşımı veya maksimum yeniden iletim miktarı gibi belirli bir koşul altında iletilmesini garanti eder. Mesajların sıralaması da yapılandırılabilir.

Paket kaybı olmadığında ilk iki modun performansı yaklaşık olarak aynıdır. Ancak güvenilir ve sıralı modda, kaybolan bir paket diğer paketlerin arkasında engellenmesine neden olur ve yeniden iletilip geldiğinde eski olabilir. Elbette aynı uygulamada birden fazla veri kanalı kullanmak mümkündür. Bu kanalların her biri kendi güvenilir veya güvenilmez semantiğine sahiptir.

Ilya Grigorik'in Yüksek Performanslı Tarayıcı Ağı adlı kitabından yararlanarak hazırladığımız faydalı tabloyu aşağıda bulabilirsiniz:

TCPUDPSCTP
GüvenilirlikGüvenilirGüvenilir değilYapılandırılabilir
Adrese teslimSipariş verildiSıralanmamışYapılandırılabilir
BulaşmaBayt odaklıMesaj odaklıMesaj odaklı
Akış kontrolüEvetHayırEvet
Yoğunluk kontrolüEvetHayırEvet

Ardından, RTCDataChannel'yı güvenilir ve sıralı veya güvenilmez ve sırasız modda kullanacak şekilde nasıl yapılandıracağınızı öğreneceksiniz.

Veri kanallarını yapılandırma

RTCDataChannel ile ilgili birkaç basit demo internette mevcuttur:

Bu örneklerde tarayıcı, kendi kendine eşler arası bağlantı kurar, ardından bir veri kanalı oluşturur ve eşler arası bağlantı üzerinden mesaj gönderir. Ardından bir veri kanalı oluşturur ve mesajı eş bağlantısı üzerinden gönderir. Son olarak, mesajınız sayfanın diğer tarafındaki kutuda görünür.

Bu özelliği kullanmaya başlamak için gereken kod kısadır:

const peerConnection = new RTCPeerConnection();

// Establish your peer connection using your signaling channel here
const dataChannel =
  peerConnection.createDataChannel("myLabel", dataChannelOptions);

dataChannel.onerror = (error) => {
  console.log("Data Channel Error:", error);
};

dataChannel.onmessage = (event) => {
  console.log("Got Data Channel Message:", event.data);
};

dataChannel.onopen = () => {
  dataChannel.send("Hello World!");
};

dataChannel.onclose = () => {
  console.log("The Data Channel is Closed");
};

dataChannel nesnesi, önceden oluşturulmuş bir eş bağlantısından oluşturulur. Sinyal verme işleminden önce veya sonra oluşturulabilir. Ardından, bu kanalı diğerlerinden ayırt etmek için bir etiket ve bir dizi isteğe bağlı yapılandırma ayarı iletirsiniz:

const dataChannelOptions = {
  ordered: false, // do not guarantee order
  maxPacketLifeTime: 3000, // in milliseconds
};

Ayrıca bir maxRetransmits seçeneği (başarısız olmadan önce denenecek sayı) de ekleyebilirsiniz ancak yalnızca maxRetransmits veya maxPacketLifeTime'ı belirtebilirsiniz, ikisini birden değil. UDP semantiği için maxRetransmits değerini 0, ordered değerini ise false olarak ayarlayın. Daha fazla bilgi için şu IETF RFC'lerine bakın: Stream Control Transmission Protocol ve Stream Control Transmission Protocol Partial Reliability Extension.

  • ordered: Veri kanalının sırayı garanti edip etmeyeceği
  • maxPacketLifeTime: Gönderilemeyen bir iletiyi yeniden iletmeyi denemek için izin verilen maksimum süre
  • maxRetransmits: Başarısız olan bir mesajı yeniden iletmeyi deneme sayısı
  • protocol: Uygulamaya yönelik meta bilgiler sağlayan bir alt protokolün kullanılmasına izin verir.
  • negotiated: true olarak ayarlanırsa diğer eşte veri kanalının otomatik olarak ayarlanmasını kaldırır ve diğer tarafta aynı kimliğe sahip bir veri kanalı oluşturmak için kendi yönteminizi kullanmanıza olanak tanır.
  • id: Kanal için kendi kimliğinizi sağlamanıza olanak tanır. Bu kimlik yalnızca negotiated değeri true olarak ayarlanmış şekilde kullanılabilir.

Çoğu kişinin kullanması gereken tek seçenekler ilk üçüdür: ordered, maxPacketLifeTime ve maxRetransmits. SCTP (artık WebRTC'yi destekleyen tüm tarayıcılar tarafından kullanılır) ile güvenilir ve sıralı varsayılan olarak doğrudur. Uygulama katmanından tam kontrol istiyorsanız güvenilir olmayan ve sıralanmamış bir şekilde kullanmak mantıklıdır ancak çoğu durumda kısmi güvenilirlik faydalıdır.

WebSocket'te olduğu gibi, RTCDataChannel bağlantı kurulduğunda, kapatıldığında veya hata oluştuğunda ve diğer eşten mesaj aldığında etkinlikleri tetiklediğini unutmayın.

Bu, güvenli mi?

Şifreleme, tüm WebRTC bileşenleri için zorunludur. RTCDataChannel ile tüm veriler Datagram Taşıma Katmanı Güvenliği (DTLS) ile korunur. DTLS, SSL'nin bir türevidir. Bu nedenle verileriniz, standart SSL tabanlı herhangi bir bağlantı kullanıyormuş gibi güvenli olur. DTLS, WebRTC'yi destekleyen tüm tarayıcılarda standartlaştırılmış ve yerleşik olarak bulunur. Daha fazla bilgi için Wireshark wiki'ye bakın.

Veriler hakkındaki düşünce şeklinizi değiştirme

Büyük miktarda verinin işlenmesi JavaScript'te zorluk yaratabilir. Sharefest'in geliştiricilerinin de belirttiği gibi, bu durum verileri yeni bir şekilde düşünmeyi gerektiriyordu. Kullanılabilir belleğinizden daha büyük bir dosyayı aktarıyorsanız bu bilgileri kaydetmek için yeni yollar düşünmeniz gerekir. Bir sonraki bölümde göreceğiniz gibi, bu noktada FileSystem API gibi teknolojiler devreye girer.

Dosya paylaşımı uygulaması oluşturma

RTCDataChannel ile artık tarayıcıda dosya paylaşabilen bir web uygulaması oluşturabilirsiniz. RTCDataChannel üzerine inşa edilmesi, aktarılan dosya verilerinin şifrelendiği ve uygulama sağlayıcının sunucularına dokunmadığı anlamına gelir. Bu işlev, daha hızlı paylaşım için birden fazla istemciye bağlanma olasılığıyla birleştiğinde WebRTC dosya paylaşımını web için güçlü bir aday haline getirir.

Başarılı bir aktarım için birkaç adım gerekir:

  1. File API'yi kullanarak JavaScript'te dosya okuma
  2. RTCPeerConnection ile istemciler arasında eşler arası bağlantı oluşturun.
  3. RTCDataChannel ile müşteriler arasında veri kanalı oluşturun.

RTCDataChannel üzerinden dosya göndermeye çalışırken dikkate alınması gereken birkaç nokta vardır:

  • Dosya boyutu: Dosya boyutu makul ölçüde küçükse ve tek bir Blob olarak depolanıp yüklenebiliyorsa File API'yi kullanarak belleğe yükleyebilir, ardından dosyayı güvenilir bir kanal üzerinden olduğu gibi gönderebilirsiniz (ancak tarayıcıların maksimum aktarım boyutuyla ilgili sınırlamalar uyguladığını unutmayın). Dosya boyutu büyüdükçe işler zorlaşır. Parçalama mekanizması gerektiğinde dosya parçaları yüklenir ve başka bir eşe gönderilir. Eşin bu parçaları tanıması için chunkID meta verileri de gönderilir. Bu durumda, parçaları önce çevrimdışı depolama alanına (ör. FileSystem API'yi kullanarak) kaydetmeniz ve dosyayı yalnızca tamamı elinizde olduğunda kullanıcının diskine kaydetmeniz gerektiğini unutmayın.
  • Parça boyutu: Bunlar, uygulamanızın en küçük veri "atomlarıdır". Şu anda bir gönderme boyutu sınırı olduğundan parçalama gereklidir (ancak bu sorun, veri kanallarının gelecekteki bir sürümünde düzeltilecektir). Maksimum parça boyutu için geçerli öneri 64 KiB'dir.

Dosya tamamen diğer tarafa aktarıldıktan sonra bir bağlantı etiketi kullanılarak indirilebilir:

function saveFile(blob) {
  const link = document.createElement('a');
  link.href = window.URL.createObjectURL(blob);
  link.download = 'File Name';
  link.click();
};

PubShare ve GitHub'daki bu dosya paylaşım uygulamaları bu tekniği kullanır. Her ikisi de açık kaynaklıdır ve RTCDataChannel tabanlı bir dosya paylaşım uygulaması için iyi bir temel sağlar.

Peki ne yapabilirsiniz?

RTCDataChannel, dosya paylaşımı, çok oyunculu oyun ve içerik dağıtımı için uygulamalar oluşturmanın yeni yollarını açıyor.

  • Daha önce açıklandığı gibi eşler arası dosya paylaşımı
  • Mozilla'nın BananaBread oyununda görüldüğü gibi, WebGL gibi diğer teknolojilerle birlikte çok oyunculu oyun
  • PeerCDN tarafından yeniden tasarlanan içerik yayınlama. Bu çerçeve, web öğelerini eşler arası veri iletişimi yoluyla yayınlar.

Uygulama geliştirme şeklinizi değiştirme

Artık RTCDataChannel üzerinden yüksek performanslı ve düşük gecikmeli bağlantılar kullanarak daha ilgi çekici uygulamalar sunabilirsiniz. PeerJS ve PubNub WebRTC SDK gibi çerçeveler, RTCDataChannel'nin uygulanmasını kolaylaştırır ve API artık platformlar arasında geniş bir destek sunar.

RTCDataChannel'nın kullanıma sunulması, tarayıcıdaki veri aktarımı hakkında düşünme şeklinizi değiştirebilir.

Daha fazla bilgi