Wysyłanie danych między dwiema przeglądarkami na potrzeby komunikacji, gier lub przesyłania plików może być dość skomplikowanym procesem. Wymaga to skonfigurowania serwera do przekazywania danych i opłacenia go, a także być może skalowania go do wielu centrów danych. W takim przypadku może wystąpić duże opóźnienie, a ochrona prywatności danych jest utrudniona.
Te problemy można rozwiązać, korzystając z interfejsu RTCDataChannel API WebRTC do przesyłania danych bezpośrednio z jednego urządzenia do drugiego. Z tego artykułu dowiesz się, jak skonfigurować i używać kanałów danych, a także poznasz typowe przypadki ich zastosowania w internecie.
Dlaczego potrzebny jest kolejny kanał danych?
Mamy WebSocket, AJAX i Server Sent Events. Dlaczego potrzebujemy kolejnego kanału komunikacji? WebSocket jest dwukierunkowy, ale wszystkie te technologie są przeznaczone do komunikacji z serwerem lub z serwera.
RTCDataChannel stosuje inne podejście:
- Działa z interfejsem
RTCPeerConnectionAPI, który umożliwia łączność peer-to-peer. Może to spowodować mniejsze opóźnienie – brak serwera pośredniczącego i mniejsza liczba „przeskoków”. RTCDataChannelkorzysta z protokołu SCTP, który umożliwia konfigurowanie semantyki dostarczania, dostarczanie poza kolejnością i konfigurację ponownego przesyłania.
RTCDataChannel jest teraz dostępny z obsługą SCTP na komputerach i urządzeniach z Androidem w przeglądarkach Google Chrome, Opera i Firefox.
Zastrzeżenie: sygnalizacja, STUN i TURN
WebRTC umożliwia komunikację peer-to-peer, ale nadal potrzebuje serwerów do sygnalizacji, aby wymieniać metadane multimediów i sieci w celu uruchomienia połączenia peer-to-peer.
WebRTC radzi sobie z NAT-ami i zaporami sieciowymi dzięki:
- ICE, aby wyznaczyć najlepszą możliwą ścieżkę sieciową między urządzeniami.
- serwery STUN, aby ustalić publicznie dostępny adres IP i port dla każdego uczestnika;
- serwery TURN, jeśli bezpośrednie połączenie się nie powiedzie i wymagane jest przekazywanie danych;
Więcej informacji o tym, jak WebRTC współpracuje z serwerami w zakresie sygnalizacji i sieci, znajdziesz w artykule WebRTC w praktyce: STUN, TURN i sygnalizacja.
Możliwości
Interfejs RTCDataChannel API obsługuje elastyczny zestaw typów danych. Interfejs API jest zaprojektowany tak, aby dokładnie naśladować WebSocket, a RTCDataChannel obsługuje ciągi znaków, a także niektóre typy binarne w JavaScript, takie jak Blob, ArrayBuffer i ArrayBufferView. Mogą być przydatne podczas przesyłania plików i gry wieloosobowej.
RTCDataChannel może działać w trybie niezawodnym i nieuporządkowanym (analogicznie do protokołu pakietów użytkownika lub UDP), w trybie niezawodnym i uporządkowanym (analogicznie do protokołu sterowania transmisją lub TCP) oraz w trybach częściowo niezawodnych:
- Tryb niezawodny i uporządkowany gwarantuje transmisję wiadomości oraz kolejność ich dostarczania. Wymaga to dodatkowych zasobów, co może spowolnić działanie tego trybu.
- Tryb nierzetelny i nieuporządkowany nie gwarantuje, że każda wiadomość dotrze do odbiorcy ani w jakiej kolejności to nastąpi. Eliminuje to dodatkowe obciążenie, dzięki czemu ten tryb działa znacznie szybciej.
- Częściowo niezawodny tryb gwarantuje transmisję wiadomości pod określonym warunkiem, np. po przekroczeniu limitu czasu ponownej transmisji lub maksymalnej liczby ponownych transmisji. Można też skonfigurować kolejność wiadomości.
W przypadku pierwszych 2 trybów wydajność jest podobna, gdy nie występują utraty pakietów. W trybie niezawodnym i uporządkowanym utracony pakiet powoduje jednak blokowanie innych pakietów, a gdy zostanie ponownie przesłany i dotrze, może być już nieaktualny. W tej samej aplikacji można oczywiście używać wielu kanałów danych, z których każdy ma własną semantykę niezawodną lub zawodną.
Oto przydatna tabela z książki High Performance Browser Networking autorstwa Ilyi Grigorika:
| TCP | UDP | SCTP | |
| Niezawodność | Niezawodne | Mało wiarygodne | Można konfigurować |
| Dostawa | Zamówiono | Nieuporządkowane | Można konfigurować |
| przenoszenia, | Zorientowane na bajty | Zorientowane na wiadomości | Zorientowane na wiadomości |
| Kontrola przepływu | Tak | Nie | Tak |
| Kontrola przeciążenia | Tak | Nie | Tak |
Następnie dowiesz się, jak skonfigurować RTCDataChannel, aby używać trybu niezawodnego i uporządkowanego lub trybu niezawodnego i nieuporządkowanego.
Konfigurowanie kanałów danych
W internecie znajdziesz kilka prostych wersji demonstracyjnych RTCDataChannel:
W tych przykładach przeglądarka nawiązuje połączenie równorzędne z samą sobą, a następnie tworzy kanał danych i wysyła wiadomość za pomocą tego połączenia. Następnie tworzy kanał danych i wysyła wiadomość za pomocą połączenia peer-to-peer. Na koniec Twoja wiadomość pojawi się w polu po drugiej stronie strony.
Kod, który umożliwia rozpoczęcie korzystania z tej funkcji, jest krótki:
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 już utworzonego połączenia równorzędnego. Można go utworzyć przed lub po wysłaniu sygnału. Następnie przekazujesz etykietę, aby 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 (liczba prób przed niepowodzeniem), ale możesz określić tylko maxRetransmits lub maxPacketLifeTime, a nie obie te opcje. W przypadku semantyki UDP ustaw maxRetransmits na 0 i ordered na false. Więcej informacji znajdziesz w tych dokumentach RFC organizacji IETF: Stream Control Transmission Protocol i Stream Control Transmission Protocol Partial Reliability Extension.
ordered: czy kanał danych powinien gwarantować kolejnośćmaxPacketLifeTime: maksymalny czas na ponowne przesłanie wiadomości, której nie udało się wysłać.maxRetransmits: maksymalna liczba prób ponownego przesłania wiadomości, której nie udało się dostarczyć.protocol: umożliwia użycie subprotokołu, który dostarcza aplikacji metadane.negotiated: jeśli ma wartość „true”, usuwa automatyczne konfigurowanie kanału danych na drugim urządzeniu, umożliwiając utworzenie kanału danych o tym samym identyfikatorze po drugiej stronie.id: umożliwia podanie własnego identyfikatora kanału, który może być używany tylko w połączeniu z parametremnegotiatedustawionym natrue.
Większość osób potrzebuje tylko 3 pierwszych opcji: ordered, maxPacketLifeTime i maxRetransmits. W przypadku SCTP (obecnie używanego przez wszystkie przeglądarki obsługujące WebRTC) niezawodność i kolejność są domyślnie ustawione na wartość true. Używanie opcji „Niezawodne i nieuporządkowane” ma sens, jeśli chcesz mieć pełną kontrolę na poziomie aplikacji, ale w większości przypadków przydatna jest częściowa niezawodność.
Pamiętaj, że podobnie jak w przypadku WebSocket, RTCDataChannel uruchamia zdarzenia, gdy połączenie zostanie nawiązane, zamknięte lub wystąpią błędy, a także gdy otrzyma wiadomość od innego urządzenia.
Czy to jest bezpieczne?
Szyfrowanie jest obowiązkowe w przypadku wszystkich komponentów WebRTC. W przypadku RTCDataChannel wszystkie dane są zabezpieczone za pomocą protokołu Datagram Transport Layer Security (DTLS). DTLS to pochodna protokołu SSL, co oznacza, że Twoje dane będą tak samo bezpieczne jak w przypadku połączenia opartego na standardowym protokole SSL. DTLS jest standardem wbudowanym we wszystkie przeglądarki obsługujące WebRTC. Więcej informacji znajdziesz w wiki Wireshark.
Zmień sposób myślenia o danych
Obsługa dużych ilości danych może być problematyczna w JavaScript. Jak zauważyli deweloperzy Sharefest, wymagało to nowego podejścia do danych. Jeśli przesyłasz plik większy niż dostępna ilość pamięci, musisz znaleźć nowe sposoby zapisania tych informacji. W tym miejscu przydają się technologie takie jak FileSystem API, o czym przekonasz się w dalszej części.
Tworzenie aplikacji do udostępniania plików
Dzięki RTCDataChannel możesz teraz tworzyć aplikacje internetowe, które umożliwiają udostępnianie plików w przeglądarce. Korzystanie z RTCDataChannel oznacza, że przesyłane dane plików są szyfrowane i nie trafiają na serwery 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 za pomocą WebRTC jest bardzo przydatne w internecie.
Aby przenieść dane, musisz wykonać kilka czynności:
- Odczytaj plik w JavaScript za pomocą interfejsu File API.
- Nawiązywanie połączeń równorzędnych między klientami za pomocą
RTCPeerConnection. - Utwórz kanał danych między klientami za pomocą
RTCDataChannel.
Podczas próby wysłania plików przez RTCDataChannel należy wziąć pod uwagę kilka kwestii:
- Rozmiar pliku: jeśli rozmiar pliku jest stosunkowo mały i można go zapisać oraz wczytać jako jeden obiekt Blob, możesz wczytać go do pamięci za pomocą interfejsu File API, a następnie wysłać przez niezawodny kanał w takiej postaci, w jakiej jest (pamiętaj jednak, że przeglądarki nakładają limity na maksymalny rozmiar przesyłania). Im większy plik, tym trudniej. Gdy wymagany jest mechanizm dzielenia na części, fragmenty plików są wczytywane i wysyłane do innego urządzenia w sieci peer-to-peer wraz z
chunkIDmetadanymi, aby urządzenie mogło je rozpoznać. Pamiętaj, że w tym przypadku musisz najpierw zapisać fragmenty w pamięci offline (np. za pomocą interfejsu FileSystem API), a następnie zapisać je na dysku użytkownika dopiero wtedy, gdy masz już cały plik. - Rozmiar fragmentu: to najmniejsze „atomy” danych w aplikacji. Fragmentowanie jest wymagane, ponieważ obecnie obowiązuje limit rozmiaru wysyłania (zostanie on jednak usunięty w przyszłej wersji kanałów danych). Obecnie zalecany maksymalny rozmiar fragmentu to 64 KiB.
Gdy plik zostanie w pełni przesłany na drugą stronę, można 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();
};
Te aplikacje do udostępniania plików na platformach PubShare i GitHub korzystają z tej techniki. Oba są oparte na licencji open source i stanowią dobrą podstawę dla aplikacji do udostępniania plików opartej na RTCDataChannel.
Co możesz zrobić?
RTCDataChannel otwiera nowe możliwości tworzenia aplikacji do udostępniania plików, gier wieloosobowych i dostarczania treści.
- Udostępnianie plików w modelu peer-to-peer w sposób opisany wcześniej.
- gry wieloosobowe w połączeniu z innymi technologiami, takimi jak WebGL, jak w przypadku BananaBread od Mozilli;
- Dostawa treści w nowej odsłonie dzięki PeerCDN, czyli platformie, która dostarcza zasoby internetowe za pomocą komunikacji peer-to-peer.
Zmień sposób tworzenia aplikacji
Możesz teraz udostępniać bardziej angażujące aplikacje, korzystając z połączeń o wysokiej wydajności i niskim opóźnieniu za pomocą RTCDataChannel. Frameworki takie jak PeerJS i PubNub WebRTC SDK ułatwiają wdrażanie RTCDataChannel, a interfejs API jest obecnie szeroko obsługiwany na różnych platformach.
Pojawienie się RTCDataChannel może zmienić sposób myślenia o przesyłaniu danych w przeglądarce.