Przesyłaj dane między przeglądarkami za pomocą kanałów danych WebRTC

Przesyłanie danych między 2 przeglądarkami w celu komunikacji, grania lub przesyłania plików może być dość żmudnym procesem. Wymaga to skonfigurowania i opłaty za serwer, który przekazuje dane, a następnie zeskalowanie go na potrzeby wielu centrów danych. W takim przypadku mogą wystąpić duże opóźnienia, a zachowanie prywatności danych jest trudne.

Te problemy można rozwiązać, używając interfejsu RTCDataChannel API WebRTC do przesyłania danych bezpośrednio z jednego połączenia do drugiego. W tym artykule znajdziesz podstawowe informacje o konfigurowaniu i korzystaniu z kanałów danych oraz o typowych przypadkach użycia w internecie.

Dlaczego inny kanał danych?

Obsługiwane są zdarzenia WebSocket, AJAX oraz Server Sent Event. Po co nam kolejny kanał komunikacji? WebSocket działa dwukierunkowo, ale wszystkie te technologie są przeznaczone do komunikacji z serwerem lub z niego.

RTCDataChannel ma inne podejście:

  • Współpracuje z interfejsem API RTCPeerConnection, który umożliwia połączenia peer-to-peer. Może to skutkować krótszym czasem oczekiwania, czyli brakiem serwera pośredniego i mniejszą liczbą „przeskoków”.
  • RTCDataChannel korzysta z protokołu SCTP (Stream Control Transmission Protocol), co pozwala na skonfigurowanie semantyki dostarczania poza kolejnością i ponownego przesyłania konfiguracji.

Usługa RTCDataChannel jest teraz dostępna z obsługą SCTP na komputerach i na Androidzie w Google Chrome, Opera i Firefoksie.

Zastrzeżenie: sygnały, STUN i TURN

WebRTC umożliwia komunikację peer-to-peer, ale wciąż potrzebuje serwerów do sygnalizowania, aby wymieniać metadane i metadane sieci w celu wczytania połączenia równorzędnego.

WebRTC radzi sobie z sieciami NAT i zaporami sieciowymi:

  • Platforma ICE do wyznaczania najlepszej możliwej ścieżki sieciowej między aplikacjami równorzędnymi.
  • Serwery STUN do sprawdzania dostępnych publicznie adresów IP i portów każdego połączenia równorzędnego.
  • Serwery TURN, jeśli nie uda się nawiązać połączenia bezpośredniego i konieczne będzie przekazywanie danych.

Więcej informacji o tym, jak WebRTC współpracuje z serwerami służącymi do sygnalizacji i sieci, znajdziesz w artykule WebRTC w świecie rzeczywistym: STUN, TURN i sygnalizacja.

Funkcje

Interfejs RTCDataChannel API obsługuje elastyczny zestaw typów danych. Interfejs API został zaprojektowany w taki sposób, aby dokładnie naśladował WebSocket, a RTCDataChannel obsługuje ciągi tekstowe, a także niektóre typy binarne w języku JavaScript, takie jak Blob, ArrayBuffer i ArrayBufferView. Te typy przydają się podczas przesyłania plików i grania wieloosobowego.

RTCDataChannel może działać w niestabilnym i nieuporządkowanym trybie (analogicznym jako protokół UDP), w trybie niezawodnym i uporządkowanym (analogicznym jak protokół TCP lub w trakcie transmisji) oraz w trybach częściowo niezawodnych:

  • Niezawodny, uporządkowany tryb gwarantuje przesyłanie wiadomości oraz kolejność ich dostarczania. Wymaga to dodatkowego nakładu pracy i może spowolnić ten tryb.
  • Niezawodny i nieuporządkowany tryb nie gwarantuje, że wszystkie wiadomości trafią na drugą stronę ani w jakiej kolejności się znajdą. Eliminuje to zbędny nakład pracy, dzięki czemu ten tryb może działać znacznie szybciej.
  • Tryb częściowej niezawodności gwarantuje przesłanie wiadomości w określonym warunku, takim jak limit czasu ponownego przesłania lub maksymalna liczba ponownych operacji przesyłania. Można też skonfigurować kolejność wiadomości.

W przypadku 2 pierwszych trybów wydajność jest mniej więcej taka sama, jeśli nie ma żadnych utraconych pakietów. Jednak w trybie niezawodnym i uporządkowanym utracony pakiet powoduje zablokowanie innych pakietów za nim, a utracony pakiet może być nieaktualny do czasu jego ponownego przesłania i dostarczenia. W tej samej aplikacji można oczywiście używać wielu kanałów danych, z których każdy ma własną niezawodną lub niepewną semantykę.

Oto przydatna tabela z artykułu High Performance Browser Networking, którego autorem jest Ilya Grigorik:

TCPUDPprotokół SCTP
NiezawodnośćNiezawodnośćMało wiarygodneKonfigurowalne
DostawaZamówienie złożoneNieuporządkowaneKonfigurowalne
przenoszenia,Zorientowana na bajtyUkierunkowana na przekazUkierunkowana na przekaz
Kontrola przepływuTakNieTak
Kontrola niedrożności błony śluzowejTakNieTak

Następnie dowiesz się, jak skonfigurować RTCDataChannel, aby używać niezawodnego i uporządkowanego trybu lub niestabilnego i nieuporządkowanego.

Konfigurowanie kanałów danych

Istnieje kilka prostych wersji demonstracyjnych usługi RTCDataChannel online:

W tych przykładach przeglądarka nawiązuje połączenie peerowe ze sobą, a następnie tworzy kanał danych i wysyła wiadomość przez takie połączenie. Następnie tworzy kanał danych i wysyła wiadomość przez połączenie równorzędne. Twoja wiadomość pojawi się w polu po drugiej stronie ekranu.

Aby zacząć z niej korzystać, musisz skorzystać z krótkiego kodu:

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

Obiekt dataChannel jest tworzony na podstawie skonfigurowanego już połączenia równorzędnego. Można go utworzyć przed sygnalizowaniem lub po nim. Następnie musisz przekazać etykietę, która pozwala odróżnić ten kanał od innych, oraz zestaw opcjonalnych ustawień konfiguracji:

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

Możesz też dodać opcję maxRetransmits (liczbę prób do momentu niepowodzenia), ale możesz określić tylko wartość maxRetransmits lub maxPacketLifeTime, a nie obie. Dla semantyki protokołu UDP ustaw maxRetransmits na 0, a ordered na false. Więcej informacji znajdziesz w tych dokumentach RFC IETF: Stream Control Transmission Protocol i Stream Control Transmission Protocol Partial Reliability Extension.

  • ordered: czy kanał danych powinien gwarantować zamówienie, czy nie
  • maxPacketLifeTime: maksymalny czas na ponowną próbę przesłania nieudanej wiadomości
  • maxRetransmits: maksymalna liczba ponownych prób przesłania wiadomości, która nie powiodła się.
  • protocol: umożliwia użycie protokołu podrzędnego, który dostarcza metainformacje o aplikacji.
  • negotiated: jeśli ma wartość Prawda, usuwa automatyczną konfigurację kanału danych u drugiego peera, umożliwiając utworzenie kanału danych z tym samym identyfikatorem po drugiej stronie.
  • id: umożliwia podanie własnego identyfikatora kanału, którego można używać tylko w połączeniu z atrybutem negotiated ustawionym na wartość true.

Większość użytkowników potrzebuje tylko trzech pierwszych opcji: ordered, maxPacketLifeTime i maxRetransmits. W przypadku SCTP (teraz używana przez wszystkie przeglądarki obsługujące WebRTC) domyślnie jest włączona niezawodność i uporządkowanie. Jeśli zależy Ci na pełnej kontroli z poziomu aplikacji, użycie niestabilnych i nieuporządkowanych danych ma sens, ale w większości przypadków pomocna jest częściowa niezawodność.

Pamiętaj, że tak jak w przypadku WebSocket, RTCDataChannel uruchamia zdarzenia w przypadku nawiązania połączenia, zamknięcia go lub wystąpienia błędów oraz odebrania komunikatu od drugiego połączenia.

Czy to jest bezpieczne?

Szyfrowanie jest obowiązkowe w przypadku wszystkich komponentów WebRTC. RTCDataChannel chroni wszystkie dane za pomocą protokołu Datagram Transport Layer Security (DTLS). DTLS jest pochodną protokołu SSL, co oznacza, że Twoje dane są równie bezpieczne jak każde standardowe połączenie oparte na protokole SSL. DTLS jest ustandaryzowane i wbudowane we wszystkie przeglądarki, które obsługują WebRTC. Więcej informacji znajdziesz na stronie wiki Wireshark.

Zmień sposób myślenia o danych

Obsługa dużych ilości danych może stanowić problem w JavaScript. Jak zauważyli deweloperzy Sharefest, wymaga to nowego spojrzenia na dane. Jeśli przesyłasz plik, który przekracza ilość dostępnej pamięci, musisz pomyśleć o nowych sposobach zapisywania tych informacji. Właśnie tu do akcji wkraczają technologie takie jak FileSystem API, jak za chwilę zobaczycie.

Tworzenie aplikacji do udostępniania plików

Dzięki RTCDataChannel można teraz utworzyć aplikację internetową, która może udostępniać pliki w przeglądarce. Połączenie plików z RTCDataChannel oznacza, że przesyłane dane plików są szyfrowane i nie mają kontaktu z serwerami dostawcy aplikacji. Ta funkcja w połączeniu z możliwością łączenia się z wieloma klientami w celu szybszego udostępniania sprawia, że udostępnianie plików WebRTC to doskonały kandydat do użytku w internecie.

Aby skutecznie przenieść konta, musisz wykonać kilka czynności:

  1. Odczytaj plik w języku JavaScript za pomocą interfejsu File API.
  2. Utwórz połączenie równorzędne między klientami za pomocą usługi RTCPeerConnection.
  3. Utwórz kanał danych między klientami za pomocą usługi RTCDataChannel.

Jeśli próbujesz wysyłać pliki przez RTCDataChannel, musisz wziąć pod uwagę kilka kwestii:

  • Rozmiar pliku: jeśli rozmiar pliku jest odpowiednio mały i można go zapisać i załadować jako jeden obiekt blob, można go załadować do pamięci przy użyciu interfejsu File API, a następnie wysłać go niezawodnym kanałem w niezmienionej postaci (pamiętaj jednak, że przeglądarki nakładają limity na maksymalny rozmiar transferu). Im większy rozmiar plików, tym trudniej jest zrobić to zadanie. Gdy wymagany jest mechanizm podziału na fragmenty, fragmenty plików są wczytywane i wysyłane do innego połączenia równorzędnego z metadanymi chunkID, aby umożliwić ich rozpoznanie. W tym przypadku musisz też zapisać fragmenty najpierw w pamięci offline (na przykład za pomocą interfejsu FileSystem API), a następnie zapisać je na dysku użytkownika tylko wtedy, gdy masz plik w całości.
  • Rozmiar fragmentu: to najmniejsze „atomy” danych w Twojej aplikacji. Podział na segmenty jest wymagany, ponieważ obecnie obowiązuje limit rozmiaru wysyłanych danych (ale zostanie on naprawiony w przyszłej wersji kanałów danych). Aktualne zalecenie dotyczące maksymalnego rozmiaru fragmentu to 64 KiB.

Po całkowitym przeniesieniu pliku na drugą stronę możesz go pobrać za pomocą tagu kotwicy:

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

Z tej metody korzystają te aplikacje do udostępniania plików w usługach PubShare i GitHub. Są to rozwiązania typu open source oparte na RTCDataChannel i stanowią solidne podstawy dla aplikacji do udostępniania plików.

Co możesz zrobić?

RTCDataChannel otwiera nowe możliwości tworzenia aplikacji do udostępniania plików, grania w tryb wieloosobowy i dostarczania treści.

  • Udostępnianie plików w modelu peer-to-peer zgodnie z wcześniejszym opisem
  • Gry wieloosobowe w połączeniu z innymi technologiami, takimi jak WebGL, takie jak w filmie Mozilla – BananaBread
  • Dostarczanie treści zaprojektowano na nowo przez platformę PeerCDN, która dostarcza zasoby internetowe przy użyciu komunikacji peer-to-peer w ramach komunikacji danych peer-to-peer

Zmień sposób tworzenia aplikacji

Teraz możesz dostarczać bardziej angażujące aplikacje, korzystając z połączeń o wysokiej wydajności i małym czasie oczekiwania w usłudze RTCDataChannel. Platformy takie jak PeerJS i PubNub WebRTC SDK ułatwiają wdrożenie RTCDataChannel, a interfejs API jest teraz obsługiwany na różnych platformach.

Pojawienie się RTCDataChannel może zmienić sposób myślenia o przenoszeniu danych w przeglądarce.

Więcej informacji