Wysyłanie danych między dwoma przeglądarkami w celu komunikacji, grania lub przesyłania plików może być dość skomplikowanym procesem. Wymaga to skonfigurowania serwera i opłacenia go za przekazywanie danych, a także ewentualnie rozszerzenia tego rozwiązania na wiele centrów danych. W takim przypadku istnieje ryzyko wysokiego czasu oczekiwania i utrzymanie prywatności danych może być trudne.
Te problemy można rozwiązać, używając interfejsu API RTCDataChannel
WebRTC do przesyłania danych bezpośrednio z jednego urządzenia do drugiego. Z tego artykułu dowiesz się, jak skonfigurować kanały danych i z nich korzystać, a także poznasz typowe przypadki użycia w internecie.
Dlaczego kolejny kanał danych?
Mamy zdarzenia WebSocket, AJAX i Server Sent Events (Zdarzenia wysłane z serwera). Dlaczego potrzebujemy innego kanału komunikacyjnego? WebSocket jest dwukierunkowy, ale wszystkie te technologie są przeznaczone do komunikacji z serwerem lub z serwerem.
RTCDataChannel
działa inaczej:
- Współpracuje z interfejsem API
RTCPeerConnection
, który umożliwia połączenia peer-to-peer. Może to spowodować mniejsze opóźnienie – brak pośredniego serwera i mniej „przeskoków”. RTCDataChannel
korzysta z protokołu Stream Control Transmission Protocol (SCTP), który umożliwia konfigurowanie semantyki przesyłania (np. przesyłanie poza kolejnością) i konfigurowanie retransmisji.
Usługa RTCDataChannel
jest teraz dostępna z obsługą SCTP na komputerach i na urządzeniach z Androidem w Google Chrome, Opera i Firefoksie.
Ostrzeżenie: Signaling, STUN i TURN
WebRTC umożliwia komunikację peer-to-peer, ale nadal wymaga serwerów do sygnalizacji, aby wymieniać metadane sieci i multimediów w celu uruchomienia połączenia peer-to-peer.
WebRTC obsługuje NAT-y i zapory sieciowe za pomocą:
- ramka ICE, która umożliwia ustalenie najlepszej możliwej ścieżki sieciowej między punktami końcowymi;
- serwery STUN, aby ustalić publicznie dostępny adres IP i port dla każdego peera.
- Włącz serwery TURN, jeśli nie uda się nawiązać bezpośredniego połączenia i wymagane jest przekazywanie danych.
Więcej informacji o tym, jak WebRTC współpracuje z serwerami sygnalizacji i sieci, znajdziesz w artykule WebRTC w praktyce: STUN, TURN i sygnalizacja.
Możliwości
Interfejs API RTCDataChannel
obsługuje elastyczny zestaw typów danych. Interfejs API został zaprojektowany tak, aby dokładnie naśladować WebSocket. RTCDataChannel
obsługuje stringi, a także niektóre typy binarne w JavaScript, takie jak Blob, ArrayBuffer i ArrayBufferView. Te typy mogą być przydatne podczas przesyłania plików i gier wieloosobowych.
RTCDataChannel
może działać w trybie niezawodnym i nieuporządkowanym (analogicznym do protokołu UDP), niezawodnym i uporządkowanym (analogicznym do protokołu TCP) oraz częściowo niezawodnym:
- Niezawodny i uporządkowany tryb gwarantuje transmisję wiadomości, a także kolejność ich dostarczania. Wymaga to dodatkowych nakładów pracy i może spowolnić ten tryb.
- Niepewny i nieuporządkowany tryb nie gwarantuje, że każda wiadomość dotrze do drugiej strony ani w jakiej kolejności. Dzięki temu nie będziesz tracić czasu na obsługę, a ten tryb będzie działać znacznie szybciej.
- Tryb częściowo niezawodny gwarantuje transmisję wiadomości w określonych warunkach, takich jak limit czasu retransmisji lub maksymalna liczba retransmisji. Kolejność wiadomości można też konfigurować.
W przypadku braku utraty pakietów wydajność w pierwszych 2 trybach jest mniej więcej taka sama. Jednak w trybie niezawodnym i uporządkowanym utracony pakiet powoduje zablokowanie innych pakietów, a w momencie, gdy zostanie on ponownie przesłany i otrzymany, może być nieaktualny. Oczywiście możesz używać wielu kanałów danych w tej samej aplikacji, z których każdy ma swoją własną niezawodną lub niewiarygodną semantykę.
Oto przydatna tabela z książki High Performance Browser Networking autorstwa Ilya Grigorik:
TCP | UDP | SCTP | |
Niezawodność | Niezawodność | Mało wiarygodne | Konfigurowalny |
Dostawa | Zamówiono | Nieuporządkowane | Konfigurowalny |
przenoszenia, | Zorientowane na bajty | oparty na wiadomościach, | oparty na wiadomościach, |
Kontrola przepływu | Tak | Nie | Tak |
Kontrola niedrożności jelit | Tak | Nie | Tak |
W następnej kolejności dowiesz się, jak skonfigurować RTCDataChannel
tak, aby używał trybu niezawodnego i uporządkowanego lub zawodnego i nieuporządkowanego.
Konfigurowanie kanałów danych
W internecie można znaleźć kilka prostych demonstracji RTCDataChannel
:
W tych przykładach przeglądarka nawiązuje połączenie równorzędne ze sobą, a następnie tworzy kanał danych i wysyła wiadomość przez połączenie równorzędne. Następnie tworzy kanał danych i wysyła wiadomość przez połączenie równorzędne. W końcu Twoja wiadomość pojawi się w polu po drugiej stronie strony.
Kod potrzebny do rozpoczęcia pracy 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 peer-to-peer. Może on zostać utworzony przed lub po sygnalizacji. 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żna też dodać opcję maxRetransmits
(liczbę prób przed niepowodzeniem), ale można określić tylko maxRetransmits lub maxPacketLifeTime, a nie oba te parametry. W przypadku semantyki UDP ustaw maxRetransmits
na 0
, a ordered
na false
. Więcej informacji znajdziesz w RFC IETF: Stream Control Transmission Protocol i Stream Control Transmission Protocol Partial Reliability Extension.
ordered
: czy kanał danych ma gwarantować kolejność.maxPacketLifeTime
: maksymalny czas na próbę i ponowne przesłanie wiadomości, której nie udało się przesłać.maxRetransmits
: maksymalna liczba prób ponownego przesłania nieudanej wiadomościprotocol
: zezwala na użycie podprotokołu, który dostarcza metadane dotyczące aplikacjinegotiated
: jeśli ustawisz wartość true (prawda), automatycznie skonfiguruje to kanał danych na drugim urządzeniu, zapewniając Ci własny sposób na utworzenie kanału danych z tym samym identyfikatorem po drugiej stronie.id
: umożliwia podanie własnego identyfikatora kanału, który może być używany tylko w połączeniu z parametremnegotiated
ustawionym natrue
.
Większość użytkowników musi używać tylko pierwszych 3 opcji: ordered
, maxPacketLifeTime
i maxRetransmits
. W przypadku SCTP (używanego obecnie przez wszystkie przeglądarki obsługujące WebRTC) domyślnie ustawione są opcje reliable i ordered. Jeśli chcesz mieć pełną kontrolę na poziomie aplikacji, warto użyć niewiarygodnych i nieuporządkowanych danych, ale w większości przypadków przydatna jest częściowa niezawodność.
Podobnie jak w przypadku WebSocket, interfejs RTCDataChannel
uruchamia zdarzenia, gdy połączenie zostanie nawiązane, zamknięte lub wystąpi błąd, a także gdy otrzyma wiadomość od innego peera.
Czy to jest bezpieczne?
Szyfrowanie jest wymagane w przypadku wszystkich komponentów WebRTC. W usłudze RTCDataChannel
wszystkie dane są chronione za pomocą protokołu Datagram Transport Layer Security (DTLS). DTLS jest pochodną protokołu SSL, co oznacza, że Twoje dane są tak samo bezpieczne jak każde standardowe połączenie SSL. DTLS jest standardem i jest wbudowany 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ć kłopotliwa w JavaScript. Jak zauważyli deweloperzy Sharefest, wymagało to nowego podejścia do danych. Jeśli przesyłasz plik, który jest większy niż dostępna ilość pamięci, musisz znaleźć nowy sposób zapisania tych informacji. Jak widać, tu do akcji wkraczają technologie takie jak FileSystem API.
Utwórz aplikację do udostępniania plików
Dzięki RTCDataChannel
możesz teraz tworzyć aplikacje internetowe, które mogą udostępniać pliki w przeglądarce. Wprowadzenie RTCDataChannel
oznacza, że przesyłane dane plików są szyfrowane i nie mają wpływu na serwery dostawcy aplikacji. Ta funkcja w połączeniu z możliwością łączenia się z większą liczbą klientów w celu szybszego udostępniania sprawia, że udostępnianie plików za pomocą WebRTC jest bardzo przydatne w internecie.
Aby przeniesienie się powiodło, musisz wykonać kilka czynności:
- Odczytaj plik w języku JavaScript za pomocą interfejsu File API.
- Nawiąż połączenie równorzędne między klientami za pomocą
RTCPeerConnection
. - Utwórz kanał danych między klientami za pomocą
RTCDataChannel
.
Podczas wysyłania plików przez sieć RTCDataChannel
należy wziąć pod uwagę kilka kwestii:
- Rozmiar pliku: jeśli rozmiar pliku jest stosunkowo mały i można go przechowywać oraz wczytywać jako jeden obiekt Blob, możesz wczytać go do pamięci za pomocą interfejsu File API, a potem wysyłać w postaci niezmodyfikowanego pliku przez niezawodny kanał (pamiętaj jednak, że przeglądarki nakładają limity na maksymalny rozmiar przesyłania). W miarę zwiększania rozmiaru pliku sytuacja się komplikuje. Gdy wymagany jest mechanizm dzielenia na części, fragmenty pliku są ładowane i wysyłane do innego peera wraz z metadanymi
chunkID
, aby ten mógł je rozpoznać. Pamiętaj, że w takim przypadku musisz też najpierw zapisać te fragmenty w pamięci offline (np. za pomocą interfejsu FileSystem API) i zapisać je na dysku użytkownika tylko wtedy, gdy masz w całości plik. - Rozmiar fragmentu: to najmniejsze „atomy” danych w aplikacji. Dzielenie na fragmenty jest wymagane, ponieważ istnieje obecnie limit wielkości przesyłanych danych (zostanie on jednak naprawiony w przyszłej wersji kanałów danych). Obecna rekomendacja dotycząca maksymalnego rozmiaru fragmentu to 64 KiB.
Gdy plik zostanie w pełni przeniesiony 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();
};
Tę technikę używają aplikacje do udostępniania plików na PubShare i GitHub. Oba są oparte na open source i stanowią dobrą podstawę dla aplikacji do udostępniania plików opartej na RTCDataChannel
.
Co możesz zrobić?
RTCDataChannel
otwiera przed Tobą nowe sposoby tworzenia aplikacji do udostępniania plików, grania w gry wieloosobowe i dostarczania treści.
- Udostępnianie plików w modelu peer-to-peer w sposób opisany wcześniej
- Gry wieloosobowe połączone z innymi technologiami, takimi jak WebGLBananaBread
- Zaprojektowana na nowo rozwiązanie PeerCDN, która pozwala dostarczać zasoby internetowe w ramach komunikacji danych typu peer-to-peer
Zmień sposób tworzenia aplikacji
Teraz możesz udostępniać bardziej angażujące aplikacje, korzystając z wysokiej jakości połączeń o niskiej latencji za pomocą RTCDataChannel
. Frameworki takie jak PeerJS i PubNub WebRTC SDK ułatwiają implementację RTCDataChannel
, a interfejs API jest teraz szeroko obsługiwany na różnych platformach.
Pojawienie się RTCDataChannel
może zmienić sposób, w jaki myślisz o przesyłaniu danych w przeglądarce.