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 może wystąpić duże opóźnienie, a dane mogą nie być chronione.
Te problemy można rozwiązać, używając interfejsu API RTCDataChannel
WebRTC do przesyłania danych bezpośrednio z jednego komputera na inny. 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 jeszcze jeden kanał danych?
Mamy WebSocket, AJAX i zdarzenia wysyłane przez serwer. Dlaczego potrzebujemy kolejnego kanału komunikacji? WebSocket jest dwukierunkowy, ale wszystkie te technologie są przeznaczone do komunikacji z serwerem lub z serwerem.
RTCDataChannel
działa inaczej:
- Działa z interfejsem API
RTCPeerConnection
, który umożliwia połączenia typu peer-to-peer. Może to spowodować mniejsze opóźnienie – brak pośredniego serwera i mniej „przeskoków”. RTCDataChannel
używa protokołu SCTP (Stream Control Transmission Protocol), który umożliwia konfigurowanie semantyki przesyłania (np. przesyłanie poza kolejnością) i konfigurowanie retransmisji.
RTCDataChannel
jest teraz dostępna z obsługą SCTP na komputerach i urządzeniach z Androidem w przeglądarkach Google Chrome, Opera i Firefox.
Uwaga: sygnalizacja, 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.
- serwery TURN, jeśli połączenie bezpośrednie się nie powiedzie 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:
- Tryb niezawodny i uporządkowany gwarantuje przesyłanie wiadomości oraz kolejność ich dostarczania. Wymaga to dodatkowych zasobów, co może spowolnić działanie tego trybu.
- 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 przesyłanie 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ść | Niezawodne | Mało wiarygodne | Można konfigurować |
Dostawa | Zamówiono | Nieuporządkowana | Można konfigurować |
przenoszenia, | Ukierunkowanie na bajty | oparty na wiadomościach, | oparty na wiadomościach, |
Kontrola przepływu | Tak | Nie | Tak |
Kontrola natężenia ruchu | Tak | Nie | Tak |
Następnie dowiesz się, jak skonfigurować RTCDataChannel
, aby używać trybu niezawodnego i uporządkowanego lub niezawodnego i nieuporządkowanego.
Konfigurowanie kanałów danych
W internecie można znaleźć kilka prostych demonstracji RTCDataChannel
:
W tych przykładach przeglądarka tworzy połączenie peer-to-peer z samą sobą, a potem tworzy kanał danych i wysyła wiadomość przez to połączenie. Następnie tworzy kanał danych i wysyła wiadomość przez połączenie peer-to-peer. 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ść, czy niemaxPacketLifeTime
: maksymalny czas na ponowne przesłanie nieudanej wiadomościmaxRetransmits
: maksymalna liczba prób retransmisji nieudanej wiadomościprotocol
: umożliwia użycie podprotokołu, który udostępnia metadane aplikacji.negotiated
: 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 potrzebuje 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ą wartości reliable i ordered o wartości true. 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 pochodnym protokołu SSL, co oznacza, że Twoje dane będą tak samo bezpieczne jak przy użyciu standardowego połączenia 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źć nowe sposoby zapisywania tych informacji. W tym miejscu wchodzą w grę technologie takie jak FileSystem API.
Tworzenie aplikacji do udostępniania plików
Dzięki RTCDataChannel
możesz teraz tworzyć aplikacje internetowe, które mogą udostępniać pliki w przeglądarce. Budowanie na podstawie RTCDataChannel
oznacza, że dane przenoszonego pliku są szyfrowane i nie są przesyłane 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 świetnym rozwiązaniem w internecie.
Aby przeniesienie się powiodło, musisz wykonać kilka czynności:
- Odczytaj plik w JavaScript za pomocą interfejsu File API.
- Utwórz 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 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 tym przypadku musisz najpierw zapisać fragmenty w magazynie offline (np. za pomocą interfejsu FileSystem API), a na dysku użytkownika zapisać je dopiero wtedy, gdy masz już cały 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();
};
Z tej techniki korzystają aplikacje do udostępniania plików w PubShare i GitHub. Oba są oprogramowaniem open source i stanowią dobry fundament 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;
- dostarczanie treści dzięki usłudze PeerCDN, 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 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ć Twoje podejście do przesyłania danych w przeglądarce.