DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Nazwa
Nazwisko
Jak chcesz czytać dzwonek?
Bez spamu

Celem tego artykułu jest zapoznanie się z jego strukturą i zasadą działania na przykładzie demo czatu wideo peer-to-peer (czat wideo p2p). W tym celu użyjemy demo czatu wideo dla wielu użytkowników webrtc.io-demo. Można go pobrać z linku: https://github.com/webRTC/webrtc.io-demo/tree/master/site.

Należy zauważyć, że GitHub jest witryną lub usługą internetową do wspólnego tworzenia projektów internetowych. Na nim programiści mogą zamieszczać kody swoich opracowań, dyskutować o nich i komunikować się ze sobą. Ponadto niektóre duże firmy informatyczne hostują na tej stronie swoje oficjalne repozytoria. Usługa jest bezpłatna dla projektów open source. GitHub to repozytorium bibliotek open source.

Umieścimy więc próbkę demo czatu wideo peer-to-peer pobraną z GitHub na dysku C komputera osobistego w utworzonym katalogu dla naszej aplikacji „webrtc_demo”.


Ryż. 1

Jak wynika ze struktury (rys. 1), wideoczat peer-to-peer składa się ze skryptów client script.js i server.js zaimplementowanych w języku programowania JavaScript. Skrypt (biblioteka) webrtc.io.js (KLIENT) - zapewnia organizację komunikacji w czasie rzeczywistym pomiędzy przeglądarkami na schemacie peer-to-peer: „klient-klient”, a webrtc.io.js (KLIENT) i webrtc .io.js (SERVER), wykorzystując protokół WebSocket, zapewniają komunikację w trybie pełnego dupleksu między przeglądarką a serwerem WWW w architekturze „klient-serwer”.

Skrypt webrtc.io.js (SERVER) jest zawarty w bibliotece webrtc.io i znajduje się w katalogu node_modules\webrtc.io\lib. Interfejs czatu wideo index.html jest zaimplementowany w HTML5 i CSS3. Zawartość plików aplikacji webrtc_demo można przeglądać za pomocą jednego z edytorów html, na przykład „Notepad ++”.

Sprawdzimy, jak działa czat wideo w systemie plików PC. Aby uruchomić serwer (server.js) na komputerze PC, musisz zainstalować środowisko uruchomieniowe node.js. Node.js umożliwia uruchamianie kodu JavaScript poza przeglądarką. Możesz pobrać node.js z linku: http://nodejs.org/ (wersja v0.10.13 z 15.07.13). Na głównej stronie witryny node.org kliknij przycisk pobierania i przejdź do http://nodejs.org/download/. W przypadku użytkowników systemu Windows najpierw pobierz win.installer (.msi), a następnie uruchom win.installer (.msi) na komputerze i zainstaluj nodejs oraz „menedżer pakietów npm” w katalogu Program Files.




Ryż. 2

Zatem node.js składa się ze środowiska programistycznego i wykonania kodu JavaScript, a także zestawu wewnętrznych modułów, które można zainstalować za pomocą menedżera lub menedżera pakietów npm.

Aby zainstalować moduły, musisz uruchomić polecenie w wierszu poleceń z katalogu aplikacji (na przykład „webrtc_demo”): npm zainstaluj nazwa_modułu... Podczas instalacji modułów menedżer npm tworzy folder node_modules w katalogu, z którego wykonano instalację. W procesie nodejs automatycznie łączy moduły z katalogu node_modules.

Tak więc po zainstalowaniu node.js otwórz wiersz poleceń i zaktualizuj moduł express w folderze node_modules katalogu webrtc_demo za pomocą menedżera pakietów npm:

C: \ webrtc_demo> npm install express

Moduł ekspresowy to framework sieciowy dla node.js lub framework sieciowy do tworzenia aplikacji. Aby mieć globalny dostęp do ekspresu, możesz zainstalować go w ten sposób: npm install -g express.

Następnie aktualizujemy moduł webrtc.io:

C: \ webrtc_demo> npm zainstaluj webrtc.io

Następnie w wierszu poleceń uruchom serwer: server.js:

C: \ webrtc_demo> node server.js


Ryż. 3

Wszystko, serwer działa pomyślnie (rysunek 3). Teraz za pomocą przeglądarki internetowej można uzyskać dostęp do serwera przez adres ip i pobrać stronę internetową index.html, z której przeglądarka internetowa wyodrębni kod skryptu klienta - script.js oraz kod skryptu webrtc.io.js, i wykonać je. Aby czat wideo peer-to-peer działał (aby nawiązać połączenie między dwiema przeglądarkami), konieczne jest, aby dwie przeglądarki obsługujące webrtc zaadresowały serwer sygnalizacyjny działający na node.js za pomocą adresu ip.

W rezultacie otworzy się interfejs części klienckiej aplikacji komunikacyjnej (czat wideo) z prośbą o zezwolenie na dostęp do kamery i mikrofonu (rys. 4).



Ryż. 4

Po kliknięciu przycisku „Zezwól” kamera i mikrofon są połączone w celu komunikacji multimedialnej. Ponadto dane tekstowe mogą być przekazywane za pośrednictwem interfejsu czatu wideo (rys. 5).



Ryż. 5

Należy zauważyć że. Serwer sygnalizuje i służy głównie do nawiązania połączenia między przeglądarkami użytkowników. Node.js służy do uruchamiania skryptu server.js, który zapewnia sygnalizację WebRTC.

Europejscy internauci dzielą się na dwie części: według badania Instytutu Analizy Opinii Publicznej w Allenbach (Niemcy) systemy Skype, czat i komunikatory stały się integralną częścią codziennego życia 16,5 mln dorosłych i dzieci9. milionów korzysta z tych usług od przypadku do przypadku, a 28 milionów nie korzysta z nich.

Może się to zmienić, gdy Firefox się teraz integruje technologia komunikacji w czasie rzeczywistym (WebRTC), a także samego klienta. Rozpoczęcie czatu audio i wideo nie jest teraz trudniejsze niż otwarcie strony internetowej. W przeciwieństwie do tego, usługi takie jak Facebook i Skype opierają się na samodzielnych rozwiązaniach do tworzenia klientów i kont.

WebRTC jest nie tylko łatwy w użyciu. Ta metoda pozwala nawet ustawić bezpośrednie połączenie między dwiema przeglądarkami... Dzięki temu dane audio i wideo nie przechodzą przez serwer, na którym może wystąpić przeciążenie lub którego administrator nie jest szczególnie wrażliwy na prywatność lub ochronę danych. Dzięki bezpośredniemu połączeniu WebRTC nie wymaga rejestracji ani konta w żadnej usłudze.

Aby rozpocząć rozmowę, wystarczy kliknąć link. Komunikacja pozostaje prywatna ponieważ strumień danych jest zaszyfrowany. Google zaczął aktywnie angażować się w komunikację w czasie rzeczywistym za pośrednictwem przeglądarki w 2011 roku, kiedy opublikował kod źródłowy implementacji WebRTC.

Wkrótce potem Chrome i Firefox otrzymały własne silniki WebRTC. Obecnie ich mobilne warianty są wyposażone zarówno w tę technologię, jak i w silnik WebView 3.6 zainstalowany z systemem Android 5.0, z którego korzystają aplikacje.

Do komunikacji w czasie rzeczywistym należy zaimplementować w przeglądarce internetowej odpowiednie interfejsy JavaScript. Dzięki GetUserMedia oprogramowanie aktywuje przechwytywanie ze źródeł audio i wideo, czyli z kamery internetowej i mikrofonu. RTCPeerConnection odpowiada za nawiązanie połączenia, a także za samą komunikację.

Równolegle z integracją przeglądarki, grupa robocza World Wide Web Consortium (W3C) przyspieszyła proces standaryzacji WebRTC. Powinno być ukończone w 2015 roku.

WebRTC jest zadowolony z małej ilości

Korzystanie z usługi WebRTC nie wymaga dużych zasobów, ponieważ serwer łączy tylko rozmówców. Nawiązanie połączenia również nie jest szczególnie trudne. Najpierw przeglądarka sygnalizuje serwerowi WebRTC, że planuje nawiązać połączenie. Otrzymuje od serwera link HTTPS - komunikacja jest szyfrowana. Użytkownik wysyła ten link do swojego rozmówcy. Przeglądarka prosi następnie użytkownika o pozwolenie na dostęp do kamery internetowej i mikrofonu.

Aby nawiązać bezpośrednie połączenie strumieniowe z rozmówcą, przeglądarka otrzymuje swój adres IP i dane konfiguracyjne z usługi WebRTC. Przeglądarka internetowa rozmówcy robi to samo.

Aby połączenie strumieniowe działało płynnie i w dobrej jakości, w przeglądarce działają trzy silniki. Dwa z nich optymalizują i kompresują dane audio i wideo, trzeci odpowiada za ich transport. Wysyła dane przez SRTP(Secure Real-time Transport Protocol), który umożliwia szyfrowane przesyłanie strumieniowe w czasie rzeczywistym.

Jeśli połączenie bezpośrednie nie powiedzie się, WebRTC szuka innej ścieżki. Na przykład dzieje się tak, gdy ustawienia sieciowe uniemożliwiają serwerowi STUN raportowanie adresu IP. Standard WebRTC przewiduje, że w tym przypadku konwersacja będzie miała miejsce, ale z pośrednim włączeniem serwera TURN (Traversal Using Relays around NAT). Tak więc na stronie netscan.co możesz sprawdzić, czy WebRTC jest zaimplementowany na Twoim komputerze i przy Twoim dostępie do sieci.

Jak nawiązywane jest połączenie

Najpierw musisz zarejestrować rozmowę (1). Usługa WebRTC udostępnia łącze, które należy wysłać do rozmówcy. Przeglądarka, korzystając z serwera STUN, znajduje własny adres IP (2), wysyła go do serwisu i otrzymuje IP partnera w celu nawiązania bezpośredniego połączenia (3). Jeśli STUN się nie powiedzie, konwersacja jest przekierowywana przy użyciu serwera TURN (4).

Komunikacja z wykorzystaniem technologii WebRTC w przeglądarce uruchamiana jest za pomocą kodu JavaScript. Następnie za komunikację odpowiadają trzy silniki: silnik głosu i wideo zbiera dane multimedialne z kamery internetowej i mikrofonu, a silnik transportu łączy informacje i przesyła strumień w postaci zaszyfrowanej za pomocą protokołu SRTP (Secure Real-time Protocol).

Które przeglądarki współpracują z WebRTC

Chrome i Firefox są wyposażone w silnik WebRTC, który korzysta z usług takich jak talky.io. Przeglądarka Mozilli może pracować bezpośrednio z własnym klientem.

Google i Mozilla nadal rozwijają ideę komunikacji w czasie rzeczywistym: Chrome może zorganizować konferencję WebRTC z wieloma uczestnikami, a nowy klient Firefox Hello jest rozwijany we współpracy z gigantem telekomunikacyjnym Telefonica. Apple na razie pozostaje na uboczu, nie powinniśmy się jeszcze spodziewać WebRTC w Safari. Istnieje jednak wiele alternatywnych aplikacji i wtyczek na iOS dla Safari.

Microsoft obiera nieco inny kurs. Jako właściciel konkurencyjnej usługi Skype, firma ta nie zamierza tak łatwo skapitulować przed WebRTC. Zamiast tego Microsoft opracowuje technologię o nazwie ORTC (Object Real-Time Communications) dla Internet Explorera.

Różnice w stosunku do WebRTC, takie jak inne kodeki i protokoły do ​​nawiązywania kontaktu z serwerem, są nieistotne i prawdopodobnie z czasem ewoluują wraz ze standardem WebRTC, który będzie obejmował te rozbieżności. Tym samym pozostało tylko Apple – jak zwykle.

Zdjęcie: firmy produkujące; goodluz / Fotolia.com

Technologie dla połączeń z przeglądarki to od wielu lat: Java, ActiveX, Adobe Flash… W ciągu ostatnich kilku lat stało się jasne, że wtyczki i maszyny wirtualne leworęczne nie świecą wygodą (dlaczego miałbym cokolwiek instalować w ogóle?) I, co najważniejsze, bezpieczeństwo ... Co robić? Jest wyjście!

Do niedawna w sieciach IP do telefonii lub wideo używano kilku protokołów: SIP, najbardziej rozpowszechniony protokół, który opuszcza scenę H.323 i MGCP, Jabber/Jingle (używany w Gtalk), półotwarty Adobe RTMP* oraz , oczywiście zastrzeżony Skype. Projekt WebRTC, zainicjowany przez Google, ma na celu zrewolucjonizowanie świata telefonii IP i sieci web poprzez wyeliminowanie wszystkich softphone'ów, w tym Skype'a. WebRTC nie tylko implementuje wszystkie możliwości komunikacji bezpośrednio w przeglądarce, która jest teraz zainstalowana na prawie każdym urządzeniu, ale jednocześnie próbuje rozwiązać bardziej ogólny problem komunikacji między użytkownikami przeglądarki (wymiana różnych danych, nadawanie ekranów, współpraca z dokumentami i wiele jeszcze).

WebRTC od strony web developera

Z punktu widzenia twórcy stron internetowych, WebRTC składa się z dwóch głównych części:

  • sterowanie strumieniami multimediów z zasobów lokalnych (kamery, mikrofonu lub lokalnego ekranu komputera) realizowane jest za pomocą metody navigator.getUserMedia, która zwraca obiekt MediaStream;
  • komunikacja peer-to-peer pomiędzy urządzeniami generującymi strumienie mediów, w tym definiowanie metod komunikacji i ich bezpośredniego przesyłania - obiekty RTCPeerConnection (do wysyłania i odbierania strumieni audio i wideo) oraz RTCDataChannel (do wysyłania i odbierania danych z przeglądarki).

Co robimy?

Dowiemy się, jak zorganizować najprostszy wieloużytkownikowy czat wideo między przeglądarkami oparty na WebRTC przy użyciu gniazd sieciowych. Zacznijmy eksperymentować w Chrome/Chromium, jako w najbardziej zaawansowanych przeglądarkach pod względem WebRTC, chociaż Firefox 22, wydany 24 czerwca, prawie ich dogonił. Trzeba powiedzieć, że standard nie został jeszcze przyjęty, a API może zmieniać się z wersji na wersję. Wszystkie przykłady zostały przetestowane w Chromium 28. Dla uproszczenia nie będziemy monitorować czystości kodu i kompatybilności z różnymi przeglądarkami.

MediaStream

Pierwszym i najprostszym komponentem WebRTC jest MediaStream. Zapewnia przeglądarce dostęp do strumieni multimedialnych z kamery i mikrofonu komputera lokalnego. W tym celu w Chrome musisz wywołać funkcję navigator.webkitGetUserMedia() (ponieważ standard nie jest jeszcze kompletny, wszystkie funkcje mają prefiks, aw Firefoksie ta sama funkcja nazywa się navigator.mozGetUserMedia()). Gdy zadzwonisz, użytkownik zostanie poproszony o pozwolenie na dostęp do kamery i mikrofonu. Kontynuowanie rozmowy będzie możliwe dopiero po wyrażeniu przez użytkownika zgody. Parametry wymaganego strumienia mediów i dwie funkcje zwrotne są przekazywane jako parametry tej funkcji: pierwsza zostanie wywołana w przypadku udanego dostępu do kamery / mikrofonu, druga w przypadku błędu. Najpierw utwórzmy plik HTML rtctest1.html z przyciskiem i elementem

WebRTC - pierwszy znajomy

Microsoft CU-RTC-Web

Microsoft nie byłby Microsoftem, gdyby w odpowiedzi na inicjatywę Google nie wypuścił od razu swojej własnej niezgodnej, niestandardowej wersji o nazwie CU-RTC-Web (html5labs.interoperabilitybridges.com/cu-rtc-web/cu-rtc-web). htm). Choć udział IE, który jest już niewielki, nadal spada, liczba użytkowników Skype'a daje Microsoftowi nadzieję na wyciśnięcie Google'a i można przypuszczać, że ten standard będzie używany w przeglądarkowej wersji Skype'a. Standard Google skupia się przede wszystkim na komunikacji między przeglądarkami; jednocześnie większość ruchu głosowego nadal pozostaje w zwykłej sieci telefonicznej, a bramy między nią a sieciami IP są potrzebne nie tylko ze względu na łatwość użytkowania czy szybszą dystrybucję, ale także jako środek monetyzacji, który pozwoli większej liczbie graczy rozwijać je... Pojawienie się kolejnego standardu może nie tylko prowadzić do nieprzyjemnej potrzeby wspierania przez programistów dwóch niekompatybilnych technologii jednocześnie, ale w dłuższej perspektywie dać użytkownikowi szerszy wybór możliwych funkcjonalności i dostępnych rozwiązań technicznych. Poczekaj i zobacz.

Włączanie strumienia lokalnego

Tagi wewnętrzne naszego pliku HTML, zadeklarujmy zmienną globalną dla strumienia mediów:

Var localStream = null;

Pierwszy parametr metody getUserMedia musi określać parametry żądanego strumienia multimediów — na przykład wystarczy włączyć audio lub wideo:

Var streamConstraints = („audio”: prawda, „wideo”: prawda); // Poproś o dostęp do audio i wideo

Lub określ dodatkowe parametry:

Var streamConstraints = ("audio": true, "video": ("mandatory": ("maxWidth": "320", "maxHeight": "240", "maxFrameRate": "5"), "opcjonalne":) );

Do drugiego parametru metody getUserMedia należy przekazać funkcję zwrotną, która zostanie wywołana, jeśli zostanie pomyślnie wykonana:

Funkcja getUserMedia_success (strumień) (console.log ("getUserMedia_success ():"), strumień); localVideo1.src = URL.createObjectURL (strumień); // Połącz strumień multimediów z elementem HTML

Trzeci parametr to funkcja zwrotna, procedura obsługi błędów, która zostanie wywołana w przypadku błędu

Funkcja getUserMedia_error (błąd) (console.log ("getUserMedia_error ():", błąd);)

Właściwie wywoływanie metody getUserMedia - żądanie dostępu do mikrofonu i kamery po naciśnięciu pierwszego przycisku

Funkcja getUserMedia_click () (console.log („getUserMedia_click ()”)); navigator.webkitGetUserMedia (streamConstraints, getUserMedia_success, getUserMedia_error);)

Nie można uzyskać dostępu do strumienia multimediów z pliku otwartego lokalnie. Jeśli spróbujemy to zrobić, otrzymamy błąd:

NavigatorUserMediaError (kod: 1, PERMISSION_DENIED: 1) "

Prześlijmy wynikowy plik na serwer, otwórzmy go w przeglądarce i w odpowiedzi na pojawiające się żądanie zezwólmy na dostęp do kamery i mikrofonu.

Możesz wybrać urządzenia, do których Chrome będzie miał dostęp w Ustawieniach, Pokaż link do ustawień zaawansowanych, Sekcja Prywatność, przycisk Treść. W przeglądarkach Firefox i Opera urządzenia są wybierane z listy rozwijanej bezpośrednio, gdy zezwala się na dostęp.

W przypadku protokołu HTTP pozwolenie będzie wymagane za każdym razem, gdy strumień multimediów zostanie uzyskany po załadowaniu strony. Przejście na HTTPS umożliwi jednokrotne wyświetlenie żądania, tylko przy pierwszym dostępie do strumienia multimediów.

Zwróć uwagę na pulsujące kółko w ikonie na zakładce oraz ikonę kamery po prawej stronie paska adresu:

Połączenie z mediami RTCM

RTCMediaConnection to obiekt przeznaczony do ustanawiania i przesyłania strumieni mediów w sieci pomiędzy uczestnikami. Ponadto obiekt ten odpowiada za generowanie opisu sesji medialnej (SDP), pozyskiwanie informacji o kandydatach ICE do przechodzenia przez NAT lub firewalle (lokalne i przy użyciu STUN) oraz interakcję z serwerem TURN. Każdy uczestnik musi mieć jedno połączenie RTCMediaConnection na połączenie. Strumienie multimediów są przesyłane za pomocą szyfrowanego protokołu SRTP.

TURN serwery

Kandydaci ICE są trzech typów: host, srflx i relay. Host zawiera informacje odbierane lokalnie, srflx - jak węzeł wygląda na serwerze zewnętrznym (STUN) oraz relay - informacje dotyczące proxy ruchu przez serwer TURN. Jeśli nasz węzeł znajduje się za NAT, kandydaci hosta będą zawierać adresy lokalne i będą bezużyteczne, kandydaci srflx pomogą tylko z niektórymi typami NAT, a przekaźnik będzie ostatnią nadzieją na przekazywanie ruchu przez serwer pośredniczący.

Przykład kandydata ICE typu host, o adresie 192.168.1.37 i porcie udp/34022:

A = kandydat: 337499441 2 udp 2113937151 192.168.1.37 34022 typ generacja hosta 0

Ogólny format określania serwerów STUN / TURN:

Serwery Var = ("iceServers": [("url": "stun: stun.stunprotocol.org: 3478"), ("url": "turn: [e-mail chroniony]: port "," poświadczenia ":" hasło ")]);

W Internecie jest wiele publicznych serwerów STUN. Na przykład jest duża lista. Niestety rozwiązują zbyt mało problemów. Praktycznie nie ma publicznych serwerów TURN, w przeciwieństwie do STUN. Wynika to z faktu, że serwer TURN przepuszcza przez siebie strumienie mediów, co może znacząco obciążać zarówno kanał sieciowy, jak i sam serwer. Dlatego najłatwiejszym sposobem połączenia się z serwerami TURN jest samodzielne zainstalowanie (oczywiste jest, że wymagany jest publiczny adres IP). Ze wszystkich serwerów rfc5766-turn-server jest moim zdaniem najlepszy. Jest nawet gotowy obraz dla Amazon EC2.

Z TURN nie wszystko jest tak dobre, jak byśmy chcieli, ale trwają aktywne prace nad rozwojem i mam nadzieję, że za jakiś czas WebRTC, jeśli nie dorówna Skype'owi w jakości przechodzenia przez translację adresów (NAT) i firewalle, to przynajmniej zauważalnie zbliży się.

RTCMediaConnection wymaga dodatkowego mechanizmu wymiany informacji sterujących w celu nawiązania połączenia - choć generuje te dane, nie przesyła ich, a transfer do innych uczestników musi być realizowany osobno.


Za wybór metody transferu odpowiada deweloper – nawet jeśli ręcznie. Gdy tylko nastąpi wymiana niezbędnych danych, RTCMediaConnection automatycznie skonfiguruje strumienie mediów (oczywiście jeśli to możliwe).

Model oferta-odpowiedź

Do ustanawiania i modyfikowania strumieni mediów wykorzystywany jest model oferty/odpowiedzi (opisany w RFC3264) oraz protokół opisu sesji (SDP). Wykorzystywane są również przez protokół SIP. W tym modelu rozróżnia się dwóch agentów: Offerer - ten, który generuje opis sesji SDP w celu utworzenia nowego lub zmodyfikowania istniejącego (Offer SDP) oraz Answerer - ten, który otrzymuje opis sesji SDP od innego agenta i odpowiada na z własnym opisem sesji (Answer SDP). Jednocześnie specyfikacja wymaga obecności protokołu wyższego poziomu (np. SIP lub własny over web sockets, jak w naszym przypadku), który odpowiada za przesyłanie SDP między agentami.

Jakie dane muszą być przesyłane między dwoma RTCMediaConnections, aby pomyślnie ustanowić strumienie multimediów:

  • Pierwszy uczestnik inicjujący połączenie tworzy Ofertę, w której przesyła strukturę danych SDP (ten sam protokół służy do tego samego celu w SIP) opisującą możliwe cechy strumienia mediów, który ma rozpocząć transmisję. Ten blok danych musi zostać przesłany do drugiego uczestnika. Drugi uczestnik tworzy odpowiedź ze swoim SDP i przesyła ją do pierwszego.
  • Zarówno pierwsi, jak i drudzy uczestnicy przeprowadzają procedurę określania ewentualnych kandydatów ICE, za pomocą których drugi uczestnik może przesyłać do nich strumień mediów. Po zidentyfikowaniu kandydatów informacje o nich należy przekazać innemu uczestnikowi.

Formowanie oferty

Do utworzenia Oferty potrzebujemy dwóch funkcji. Pierwszy zostanie wywołany, jeśli zostanie pomyślnie utworzony. Drugim parametrem metody createOffer() jest funkcja zwrotna, która jest wywoływana w przypadku wystąpienia błędu podczas jej wykonywania (pod warunkiem, że strumień lokalny jest już dostępny).

Dodatkowo potrzebne są dwa programy obsługi zdarzeń: onicecandidate podczas definiowania nowego kandydata ICE i onaddstream podczas podłączania strumienia mediów z odległej strony. Wróćmy do naszych akt. Dodaj do HTML po liniach z elementami

A po linii z żywiołem


Ponadto na początku kodu JavaScript deklarujemy zmienną globalną dla RTCPeerConnection:

War pc1;

Podczas wywoływania konstruktora RTCPeerConnection należy określić serwery STUN/TURN. Zobacz pasek boczny, aby uzyskać więcej informacji; dopóki wszyscy uczestnicy są w tej samej sieci, nie są one wymagane.

Serwery Var = null;

Parametry przygotowania oferty SDP

Oferta VarOgraniczenia = ();

Pierwszym parametrem metody createOffer() jest funkcja zwrotna, która jest wywoływana po pomyślnym wygenerowaniu oferty.

Funkcja pc1_createOffer_success (desc) (console.log („pc1_createOffer_success (): \ ndesc.sdp: \ n” + desc.sdp + „desc:”, opis); pc1.setLocalDescription (opis); // Ustaw RTCPeerConnection wygenerowane przez ofertę SDP przy użyciu metody setLocalDescription // Gdy druga strona wysyła odpowiedź SDP, należy ją ustawić przy użyciu metody setRemoteDescription // Do czasu implementacji drugiej strony nic nie rób // pc2_receivedOffer (desc);)

Drugi parametr to funkcja zwrotna, która zostanie wywołana w przypadku błędu

Funkcja pc1_createOffer_error (błąd) (console.log („pc1_createOffer_success_error (): błąd:”, błąd);)

A my zadeklarujemy funkcję zwrotną, do której kandydaci ICE zostaną przekazani tak, jak są zdefiniowani:

Funkcja pc1_onicecandidate (zdarzenie) (jeśli (event.candidate) (console.log ("pc1_onicecandidate ():): \ n" + event.candidate.candidate.replace ("\ r \ n", ""), event.candidate); // Dopóki druga strona nie zostanie zaimplementowana, nic nie rób // pc2.addIceCandidate (new RTCIceCandidate (event.candidate));))

A także funkcję zwrotną do dodawania strumienia mediów z dalekiej strony (na przyszłość, ponieważ do tej pory mamy tylko jedno RTCPeerConnection):

Funkcja pc1_onaddstream (zdarzenie) (console.log („pc_onaddstream ()”)); remoteVideo1.src = URL.createObjectURL (zdarzenie.stream);)

Po kliknięciu przycisku „createOffer” utwórz połączenie RTCPeerConnection, ustaw metody onicecandidate i onaddstream i poproś o utworzenie Offer SDP, wywołując metodę createOffer():

Funkcja createOffer_click () (console.log („createOffer_click ()”)); pc1 = new webkitRTCPeerConnection (serwery); // Utwórz RTCPeerConnection pc1.onicecandidate = pc1_onicecandidate; // Funkcja wywołania zwrotnego do przetwarzania kandydatów ICE pc1._onaddstream = pc1 // Callback -funkcja wywoływana, gdy strumień multimediów pojawia się z dalekiej strony.Nie jest jeszcze dostępny pc1.addStream (localStream);// Przenieśmy lokalny strumień multimediów (zakładamy, że już został odebrany) pc1.createOffer (// I faktycznie prosimy o utworzenie oferty pc1_createOffer_success , pc1_createOffer_error, offerConstraints);)

Zapiszmy plik jako rtctest2.html, umieśćmy go na serwerze, otwórzmy w przeglądarce i zobaczmy w konsoli jakie dane są generowane podczas jego działania. Drugi film jeszcze się nie pojawi, ponieważ jest tylko jeden uczestnik. Przypomnijmy, że SDP to opis parametrów sesji medialnej, dostępne kodeki, strumienie mediów i kandydaci ICE są możliwymi opcjami połączenia z danym uczestnikiem.

Odpowiedz Formacja SDP i Wymiana Kandydatów ICE

Zarówno Offer SDP, jak i każdy z kandydatów ICE musi zostać przekazany na drugą stronę i tam, po otrzymaniu ich z RTCPeerConnection, wywołać metody setRemoteDescription dla Offer SDP i addIceCandidate dla każdego otrzymanego z drugiej strony kandydata ICE; Podobnie w odwrotnej kolejności dla Answer SDP i zdalnych kandydatów ICE. Sama odpowiedź SDP jest tworzona w taki sam sposób jak Oferta; różnica polega na tym, że nie jest wywoływana metoda createOffer, ale metoda createAnswer, a przed tym RTCPeerConnection Offer SDP odebrany od wywołującego jest przekazywany przez metodę setRemoteDescription.

Dodajmy kolejny element wideo do HTML:

I zmienna globalna dla drugiego RTCPeerConnection pod pierwszym:

War pc2;

Oferta i odpowiedź Przetwarzanie SDP

Odpowiedź Generowanie SDP jest bardzo podobne do oferty. W funkcji callback, wywoływanej po pomyślnym utworzeniu Odpowiedzi, podobnie jak w Ofercie, podajemy opis lokalny i przekazujemy otrzymaną odpowiedź SDP pierwszemu uczestnikowi:

Funkcja pc2_createAnswer_success (desc) (pc2.setLocalDescription (desc); console.log ("pc2_createAnswer_success ()", desc.sdp); pc1.setRemoteDescription (desc);)

Funkcja callback, wywoływana w przypadku błędu podczas tworzenia odpowiedzi, jest całkowicie podobna do Offer:

Funkcja pc2_createAnswer_error (błąd) (console.log („pc2_createAnswer_error ():”, błąd);)

Parametry generowania odpowiedzi SDP:

Var answerConstraints = ("mandatory": ("OfferToReceiveAudio": true, "OfferToReceiveVideo": true));

Po otrzymaniu Oferty przez drugiego uczestnika utwórz połączenie RTCPeerConnection i utwórz odpowiedź podobnie do oferty:

Funkcja pc2_receivedOffer (desc) (console.log („pc2_receiveOffer ()”), opis); // Utwórz obiekt RTCPeerConnection dla drugiego uczestnika w taki sam sposób jak pierwszy pc2 = new webkitRTCPeerConnection (serwery); pc2.onicecandidate = pc2_onicecandidate; // Ustaw kandydata do obsługi zdarzeń ICE pc2.onaddstream = pc_onaddstream; // Gdy pojawi się strumień, połącz go z kodem HTML

Aby w ramach naszego przykładu przekazać Ofertę SDP od pierwszego uczestnika do drugiego, odkomentujmy w funkcji pc1 tworzenie oferty sukces () ciąg wywołania:

Pc2_receivedOffer (opis);

Aby zaimplementować przetwarzanie kandydatów ICE, odkomentujmy procedurę obsługi zdarzenia gotowości kandydata ICE pierwszego uczestnika pc1_onicecandidate(), aby przekazać ją drugiemu:

Pc2.addIceCandidate (nowy RTCIceCandidate (zdarzenie.candidate));

Drugi program obsługi zdarzenia gotowości uczestnika dla kandydatów ICE jest odzwierciedlony jak pierwszy:

Funkcja pc2_onicecandidate (zdarzenie) (if (event.candidate) (console.log („pc2_onicecandidate ():”), event.candidate.candidate); pc1.addIceCandidate (nowy RTCIceCandidate (event.candidate));))

Funkcja oddzwaniania do dodania strumienia multimediów od pierwszego uczestnika:

Funkcja pc2_onaddstream (zdarzenie) (console.log („pc_onaddstream ()”)); remoteVideo2.src = URL.createObjectURL (zdarzenie.stream);)

Zakończenie połączenia

Dodajmy kolejny przycisk do HTML

I funkcja zakończenia połączenia

Funkcja btnHangupClick (// Odłącz lokalne wideo od elementów HTML

Zapiszmy go jako rtctest3.html, umieśćmy na serwerze i otwórzmy w przeglądarce. Ten przykład implementuje dwukierunkowe przesyłanie strumieniowe multimediów między dwoma RTCPeerConnections w ramach tej samej zakładki przeglądarki. Aby zorganizować wymianę Oferty i Odpowiedzi SDP, kandydatów ICE między uczestnikami i innymi informacjami za pośrednictwem sieci, zamiast bezpośredniego wezwania procedur, konieczne będzie wdrożenie wymiany między uczestnikami z wykorzystaniem pewnego rodzaju transportu, w naszym przypadku, gniazda sieciowe.

Transmisja ekranowa

Funkcja getUserMedia może również przechwytywać ekran i transmitować jako MediaStream, określając następujące parametry:

Var mediaStreamConstraints = (audio: false, video: (obowiązkowe: (chromeMediaSource: "screen"), opcjonalne:));

Aby uzyskać dostęp do ekranu, należy spełnić kilka warunków:

  • włącz flagę zrzutu ekranu w getUserMedia () w chrome: // flags /, chrome: // flags /;
  • plik źródłowy musi być przesłany przez HTTPS (pochodzenie SSL);
  • nie należy żądać strumienia audio;
  • nie należy wykonywać wielu żądań w jednej karcie przeglądarki.

Biblioteki dla WebRTC

Chociaż WebRTC nie jest jeszcze ukończony, istnieje już kilka bibliotek na nim opartych. JsSIP jest przeznaczony do tworzenia telefonów programowych opartych na przeglądarce, które współpracują z przełącznikami SIP, takimi jak Asterisk i Camalio. PeerJS uprości tworzenie sieci P2P do wymiany danych, a Holla zmniejszy ilość prac programistycznych wymaganych do komunikacji P2P z przeglądarek.

Node.js i socket.io

W celu zorganizowania wymiany kandydatów SDP i ICE między dwoma RTCPeerConnections przez sieć, używamy Node.js z modułem socket.io.

Opisano instalację najnowszej stabilnej wersji Node.js (dla Debiana / Ubuntu)

$ sudo apt-get install python-software-properties python g ++ make $ sudo add-apt-repository ppa: chris-lea / node.js $ sudo apt-get update $ sudo apt-get install nodejs

Opisano instalację dla innych systemów operacyjnych

Sprawdźmy:

$ echo "sys = wymagają (" util "); sys.puts (" Wiadomość testowa ");" > nodetest1.js $ nodejs nodetest1.js

Zainstaluj socket.io i ekspresowy dodatek za pomocą npm (Node Package Manager):

$ npm zainstaluj socket.io express

Sprawdźmy, tworząc plik nodetest2.js po stronie serwera:

$ nano nodetest2.js var app = require ("express") (), server = require ("http").createServer (app), io = require ("socket.io").listen (serwer); server.listen (80); // Jeśli port 80 jest wolny app.get ("/", function (req, res) (// Podczas dostępu do strony głównej res.sendfile (__ dirname + "/nodetest2.html"); // wyślij plik HTML )) ; io.sockets.on ("połączenie", funkcja (gniazdo) (// podczas podłączania socket.emit ("zdarzenie serwera", (hello: "świat"));) // wyślij wiadomość socket.on ("zdarzenie klienta", function (data) (// i zadeklaruj procedurę obsługi zdarzenia, gdy wiadomość nadejdzie z klienta console.log (data);));));

Oraz nodetest2.html po stronie klienta:

$ nano nodetest2.html

Zacznijmy serwer:

$ sudo nodejs nodetest2.js

i otwórz stronę http://localhost:80 (jeśli działa lokalnie na porcie 80) w przeglądarce. Jeśli wszystko się powiedzie, w konsoli JavaScript przeglądarki zobaczymy wymianę zdarzeń między przeglądarką a serwerem po połączeniu.

Wymiana informacji między RTCPeerConnection przez websockets

Część klienta

Zapiszmy nasz główny przykład (rtcdemo3.html) pod nową nazwą rtcdemo4.html. Podłączmy bibliotekę socket.io w elemencie:

A na początek skrypt JavaScript - łączenie się z websocketami:

Gniazdo Var = io.connect ("http: // localhost");

Zastąpmy bezpośrednie wywołanie funkcji innego uczestnika wysyłaniem mu wiadomości przez web sockets:

Funkcja createOffer_success (opis) (... // pc2_receivedOffer (opis); socket.emit ("oferta", opis); ...) funkcja pc2_createAnswer_success (opis) (... // pc1.setRemoteDescription (opis); gniazdo .emit ("odpowiedź", opis);) funkcja pc1_onicecandidate (zdarzenie) (... // pc2.addIceCandidate (nowy RTCIceCandidate (zdarzenie.candidate)); socket.emit ("ice1", wydarzenie.candidate); .. .) function pc2_onicecandidate (zdarzenie) (... // pc1.addIceCandidate (nowy RTCIceCandidate (event.candidate)); socket.emit ("ice2", zdarzenie.candidate); ...)

W funkcji hangup() zamiast bezpośrednio wywoływać funkcje drugiego uczestnika, przekaż wiadomość przez gniazda sieciowe:

Funkcja btnHangupClick () (... // remoteVideo2.src = ""; pc2.close (); pc2 = null; socket.emit ("zakończ", ());)

I dodaj programy obsługi do odbierania wiadomości:

Socket.on („oferta”, funkcja (dane) (console.log („socket.on („oferta”):”, dane); pc2_receivedOffer (dane);)); socket.on („odpowiedź”, funkcja (dane) (e console.log („socket.on („odpowiedź”)):”, dane); pc1.setRemoteDescription (nowy RTCSessionDescription (dane));)); socket.on („ice1”, funkcja (dane) (console.log („socket.on („ice1”)):”, dane); pc2.addIceCandidate (nowy RTCIceCandidate (dane));)); socket.on („ice2”, funkcja (dane) (console.log („socket.on („ice2”):”, dane); pc1.addIceCandidate (nowy RTCIceCandidate (dane));)); socket.on („zawieszenie”, funkcja (dane) (console.log („socket.on („zawieszenie”)):”, dane); remoteVideo2.src = „”; pc2.close (); pc2 = null;) );

Część serwerowa

Po stronie serwera zapisz plik nodetest2 pod nową nazwą rtctest4.js i dodaj odbieranie i wysyłanie komunikatów klienta wewnątrz funkcji io.sockets.on ("połączenie", funkcja (socket) (...)):

Socket.on („oferta”, funkcja (dane) (// po odebraniu komunikatu „oferta”, // ponieważ w tym przykładzie istnieje tylko jedno połączenie klienta, // odeślij komunikat przez to samo gniazdo socket.emit ("oferta" , dane); // Jeśli trzeba było wysłać wiadomość we wszystkich połączeniach, // poza nadawcą: // soket.broadcast.emit ("oferta", dane);)); socket.on („odpowiedź”, funkcja (dane) (socket.emit („odpowiedź”, dane);)); socket.on („ice1”, funkcja (dane) (socket.emit („ice1”, dane);)); socket.on („ice2”, funkcja (dane) (socket.emit („ice2”, dane);)); socket.on („zawieszenie”, funkcja (dane) (socket.emit („zawieszenie”, dane);));

Dodatkowo zmienimy nazwę pliku HTML:

// res.sendfile (__ nazwa_katalogu + "/nodetest2.html"); // Wyślij plik HTML res.sendfile (__ dirname + "/rtctest4.html");

Start serwera:

$ sudo nodejs nodetest2.js

Pomimo tego, że kod obu klientów jest wykonywany w ramach tej samej zakładki przeglądarki, cała interakcja między uczestnikami w naszym przykładzie odbywa się w całości za pośrednictwem sieci i nie wymaga żadnych specjalnych komplikacji, aby „oddzielić” uczestników. Jednak to, co zrobiliśmy, było również bardzo proste – te technologie są dobre ze względu na łatwość ich użycia. Nawet jeśli czasami oszukuje. W szczególności nie zapominajmy, że bez serwerów STUN/TURN nasz przykład nie może działać w obecności translacji adresów i zapór ogniowych.

Wniosek

Otrzymany przykład jest bardzo warunkowy, ale jeśli nieco zuniwersalizujemy obsługę zdarzeń, aby nie różniły się od wywołującego i wywoływanego, zamiast dwóch obiektów pc1 i pc2, utwórz tablicę RTCPeerConnection i zaimplementuj dynamiczne tworzenie i usuwanie elementów

Możemy przypuszczać, że już niedługo dzięki WebRTC nastąpi rewolucja nie tylko w naszym rozumieniu komunikacji głosowej i wideo, ale także w postrzeganiu Internetu w ogóle. WebRTC jest pozycjonowany nie tylko jako technologia połączeń z przeglądarki do przeglądarki, ale także jako technologia komunikacji w czasie rzeczywistym. Przeanalizowana przez nas komunikacja wideo to tylko niewielka część możliwych opcji jej wykorzystania. Istnieją już przykłady screencastingu i współpracy, a nawet opartej na przeglądarce sieci dostarczania treści P2P przy użyciu RTCDataChannel.

Dzisiaj WebRTC to najgorętsza technologia do strumieniowego przesyłania dźwięku i wideo w przeglądarkach. Konserwatywne technologie, takie jak HTTP Streaming i Flash, są bardziej odpowiednie do dystrybucji zarejestrowanych treści (wideo na żądanie) i znacznie ustępują WebRTC pod względem transmisji w czasie rzeczywistym i online, tj. gdzie wymagane jest minimalne opóźnienie wideo, aby widzowie mogli zobaczyć, co dzieje się „na żywo”.

Możliwość wysokiej jakości komunikacji w czasie rzeczywistym pochodzi z samej architektury WebRTC, w której do przesyłania strumieni wideo wykorzystywany jest protokół UDP, który jest standardową podstawą transmisji wideo z minimalnymi opóźnieniami i jest szeroko stosowany w systemach komunikacji czasu rzeczywistego.

Opóźnienie komunikacji jest ważne w systemach transmisji online, seminariach internetowych i innych aplikacjach, w których wymagana jest interaktywna komunikacja ze źródłem wideo, użytkownikami końcowymi i rozwiązaniem.

Kolejnym dobrym powodem do wypróbowania WebRTC jest zdecydowanie trend. Dziś każda przeglądarka Chrome na Androida obsługuje tę technologię, co gwarantuje miliony urządzeń gotowych do oglądania transmisji bez konieczności instalowania dodatkowego oprogramowania czy konfiguracji.

Aby przetestować technologię WebRTC w działaniu i uruchomić na niej prostą transmisję online, wykorzystaliśmy oprogramowanie Flashphoner WebRTC Media & Broadcasting Server. Funkcje deklarują możliwość nadawania strumieni WebRTC w trybie jeden-do-wielu, a także obsługę kamer IP i systemów nadzoru wideo za pośrednictwem protokołu RTSP; w tym przeglądzie skupimy się na webcastingu i jego funkcjach.

Instalowanie serwera mediów i transmisji WebRTC

Ponieważ nie było wersji serwerowej dla systemu Windows, a nie chciałem instalować maszyny wirtualnej, takiej jak VMWare + Linux, nie mogłem testować transmisji online na moim domowym komputerze z systemem Windows. Aby zaoszczędzić czas, zdecydowaliśmy się na skorzystanie z takiej instancji na hostingu w chmurze:

Był to Centos x86_64 w wersji 6.5 bez żadnego preinstalowanego oprogramowania w centrum danych w Amsterdamie. Zatem wszystko, co mamy do dyspozycji, to serwer i dostęp do niego przez ssh. Dla tych, którzy znają polecenia konsoli Linuksa, instalacja serwera WebRTC zapowiada się prosto i bezboleśnie. Więc co zrobiliśmy:

1. Pobierz archiwum:

$ wget https: //site/download-wcs5-server.tar.gz

2. Rozpakować:

$ tar -xzf download-wcs5-server.tar.gz

3. Zainstalować:

$ cd FlashphonerWebCallServer

Podczas instalacji wprowadź adres IP serwera: XXX.XXX.XXX.XXX

4. Aktywuj licencję:

$ cd / usr / lokalny / FlashphonerWebCallServer / bin

$. / aktywacja.sh

5. Uruchom serwer WCS:

$ usługa webcallserver start

6. Sprawdź dziennik:

$ ogon - f /usr/local/FlashphonerWebCallServer/logs/flashphoner_manager.log

7. Sprawdź, czy istnieją dwa procesy:

$ ps aux | grep Flashphoner

Proces instalacji został zakończony.

Testowanie transmisji internetowych WebRTC

Testowanie transmisji okazało się prostą sprawą. Oprócz serwera istnieje klient sieciowy, który składa się z kilkunastu plików Javascript, HTML i CSS i został przez nas wdrożony do folderu /var/www/html podczas fazy instalacji. Jedyne, co trzeba było zrobić, to wpisać adres IP serwera w konfiguracji flashphoner.xml, aby klient sieciowy mógł nawiązać połączenie z serwerem za pośrednictwem HTML5 Websockets. Opiszmy proces testowania.

1. Otwórz stronę klienta testowego index.html w przeglądarce Chrome:

2. Aby rozpocząć nadawanie, musisz nacisnąć przycisk „Start” na środku ekranu.
Zanim to zrobisz, upewnij się, że kamera internetowa jest podłączona i gotowa do użycia. Nie ma specjalnych wymagań co do kamery internetowej, np. zastosowaliśmy standardową kamerę wbudowaną w laptopa o rozdzielczości 1280×800.

Przeglądarka Chrome na pewno poprosi o dostęp do kamery i mikrofonu, aby użytkownik zrozumiał, że jego wideo zostanie przesłane na serwer internetowy i na to pozwoli.

3. Interfejs jest pomyślną transmisją strumienia wideo z kamery do serwera WebRTC. W prawym górnym rogu wskaźnik wskazuje, że strumień trafia na serwer, w dolnym rogu znajduje się przycisk Stop, aby zatrzymać wysyłanie wideo.

Zwróć uwagę na link w polu poniżej. Zawiera unikalny identyfikator tego strumienia, więc każdy może dołączyć do widoku. Wystarczy otworzyć ten link w przeglądarce. Aby skopiować go do schowka, kliknij przycisk „Kopiuj”.

W rzeczywistych aplikacjach, takich jak webinaria, wykłady, transmisje wideo online lub telewizja interaktywna, programiści będą musieli wdrożyć dystrybucję tego identyfikatora do określonych grup widzów, aby mogli połączyć się z niezbędnymi strumieniami, ale taka jest logika aplikacji. Serwer mediów i transmisji WebRTC nie ma na to wpływu, a jedynie zajmuje się dystrybucją wideo.

5. Połączenie zostaje nawiązane, a widz widzi strumień na ekranie. Teraz może wysłać link do kogoś innego, przestać odtwarzać transmisję lub włączyć tryb pełnoekranowy za pomocą elementów sterujących w prawym dolnym rogu.

Wyniki testów serwera WebRTC transmisji online

Podczas testów latencja wyglądała idealnie. Ping do centrum danych trwał około 100 milisekund, a opóźnienie było niewidoczne dla oka. W związku z tym możemy założyć, że rzeczywiste opóźnienie jest takie samo 100 plus minus kilkadziesiąt milisekund dla czasu buforowania. W porównaniu do wideo we Flashu: w takich testach Flash nie zachowuje się tak dobrze jak WebRTC. Jeśli więc poruszasz ręką w podobnej sieci, ruch na ekranie widać dopiero po jednej/dwóch sekundach.

Jeśli chodzi o jakość, zauważamy, że czasami można odróżnić kostki na ruchach. Jest to zgodne z naturą kodeka VP8 i jego głównym celem - zapewnieniem komunikacji wideo w czasie rzeczywistym o akceptowalnej jakości i bez opóźnień w komunikacji.

Serwer jest dość prosty w instalacji i konfiguracji, do jego uruchomienia nie potrzeba żadnych poważnych umiejętności poza znajomością Linuksa na poziomie zaawansowanego użytkownika, który potrafi wykonywać polecenia z konsoli przez ssh i korzystać z edytora tekstu. W rezultacie udało nam się ustanowić transmisję jeden-do-wielu online między przeglądarkami. Podłączenie dodatkowych widzów do streamu również nie sprawiało problemów.

Jakość transmisji okazała się całkiem akceptowalna w przypadku webinariów i transmisji internetowych. Jedyną rzeczą, która budziła pewne pytania, była rozdzielczość wideo. Kamera obsługuje 1280x800, ale rozdzielczość na zdjęciu testowym jest bardzo zbliżona do 640x480. Najwyraźniej to pytanie wymaga wyjaśnienia z twórcami.

Wideo do testowania transmisji z kamery internetowej
przez serwer WebRTC

WebRTC to interfejs API udostępniany przez przeglądarkę, który umożliwia organizowanie połączenia P2P i przesyłanie danych bezpośrednio między przeglądarkami. W Internecie jest sporo samouczków dotyczących pisania własnego czatu wideo za pomocą WebRTC. Na przykład, oto artykuł o Habré. Jednak wszystkie ograniczają się do połączenia dwóch klientów. W tym artykule postaram się opowiedzieć o tym, jak zorganizować połączenie i wymianę wiadomości między trzema lub więcej użytkownikami za pomocą WebRTC.

Interfejs RTCPeerConnection to połączenie typu peer-to-peer między dwiema przeglądarkami. Aby połączyć trzech lub więcej użytkowników, będziemy musieli zorganizować sieć mesh (sieć, w której każdy węzeł jest połączony ze wszystkimi innymi węzłami).
Użyjemy następującego schematu:

  1. Otwierając stronę, sprawdzamy, czy w pokoju znajduje się numer identyfikacyjny pokoju lokalizacja.hasz
  2. Jeśli numer pokoju nie jest podany, generujemy nowy
  3. Wysyłamy serwerowi sygnalizacyjnemu wiadomość, że chcemy dołączyć do określonego pokoju
  4. Serwer sygnalizacyjny wysyła powiadomienie nowego użytkownika do pozostałych klientów w tym pomieszczeniu.
  5. Klienci, którzy są już w pokoju, wysyłają nowicjuszowi ofertę SDP
  6. Nowicjusz odpowiada na ofertę

0. Serwer sygnalizacyjny

Jak wiecie, chociaż WebRTC zapewnia połączenie P2P między przeglądarkami, nadal wymaga dodatkowego transportu do wymiany komunikatów usług. W tym przykładzie takim transportem jest serwer WebSocket napisany w Node.JS przy użyciu socket.io:

Var socket_io = wymagaj ("socket.io"); module.exports = function (serwer) (var users = (); var io = socket_io (serwer); io.on ("połączenie", funkcja (gniazdo)) (// Nowy użytkownik chce dołączyć do pokoju socket.on (" room ", function (message) (var json = JSON.parse (message); // Dodaj gniazdo do listy użytkowników users = socket; if (socket.room! == undefined) (// Jeśli gniazdo jest już w jakimś pokoju wyjdź z niego socket.leave (socket.room);) // Wprowadź żądany pokój socket.room = json.room; socket.join (socket.room); socket.user_id = json.id; // Wyślij do innych klientów w tym pokoju wiadomość o dołączeniu nowego uczestnika do socket.broadcast.to (socket.room) .emit ("nowy", json.id);)); // Wiadomość związana z WebRTC (oferta SDP, odpowiedź SDP lub ICE kandydata) socket.on („webrtc”, function (wiadomość) (var json = JSON.parse (wiadomość); if (json.to! == undefined && users! == undefined) (// Jeśli wiadomość zawiera odbiorca i ten odbiorca znany serwerowi, wysyłamy wiadomość tylko do niego ... users.emit ("webrtc", wiadomość); ) else (// ... w przeciwnym razie traktuj komunikat jako rozgłoszeniowe socket.broadcast.to (socket.room) .emit ("webrtc", komunikat;))); // Ktoś się rozłączył socket.on ("rozłącz", funkcja() (// Gdy klient się rozłącza, powiadom o tym innych socket.broadcast.to (socket.room) .emit ("opuść", socket.user_id); użytkownicy;)); )); );

1.index.html

Kod źródłowy samej strony jest dość prosty. Celowo nie zwracałem uwagi na układ i inne piękności, ponieważ ten artykuł nie dotyczy tego. Jeśli ktoś chce ją upiększyć, nie będzie to trudne.

Demo czatu WebRTC

Połączony z 0 rówieśnicy

2.main.js

2.0. Uzyskiwanie linków do elementów strony i interfejsów WebRTC
var chatlog = document.getElementById („chatlog”); var wiadomość = document.getElementById ("wiadomość"); var numer_połączenia = document.getElementById ("numer_połączenia"); var room_link = document.getElementById („room_link”);

Nadal musimy używać prefiksów przeglądarki, aby odnosić się do interfejsów WebRTC.

Var PeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; var SessionDescription = window.mozRTCSessionDescription || okno.RTCSessionDescription; var IceCandidate = window.mozRTCIceCandidate || okno.RTCIceCandidate;

2.1. Ustalenie identyfikatora pokoju

Tutaj potrzebujemy funkcji do wygenerowania unikalnego identyfikatora pokoju i użytkownika. Do tych celów użyjemy UUID.

Funkcja uuid () (var s4 = function () (return Math.floor (Math.random () * 0x10000) .toString (16);); return s4 () + s4 () + "-" + s4 () + „-” + s4 () + „-” + s4 () + „-” + s4 () + s4 () + s4 ();)

Teraz spróbujmy wyciągnąć identyfikator pokoju z adresu. Jeśli żaden nie zostanie określony, wygenerujemy nowy. Wyświetlmy na stronie link do aktualnego pokoju i w jednym kroku wygenerujmy aktualny identyfikator użytkownika.

Var POKÓJ = lokalizacja.hash.substr (1); if (! ROOM) (ROOM = uuid ();) room_link.innerHTML = "Link do pokoju"; zmienna ME = uuid ();

2.2. Gniazdo sieciowe

Zaraz po otwarciu strony połączymy się z naszym serwerem sygnalizacyjnym, wyślemy prośbę o wejście do pokoju i określimy obsługę wiadomości.

// Wskazujemy, że gdy wiadomość zostanie zamknięta, powiadomienie o tym powinno zostać wysłane do serwera var socket = io.connect ("", ("sync Disconnect on unload": true)); socket.on ("webrtc", socketReceived); socket.on ("nowy", socketNewPeer); // Natychmiast wyślij żądanie wejścia do pokoju socket.emit ("pokój", JSON.stringify ((id: ME, pokój: POKÓJ))); // Funkcja pomocnicza do wysyłania wiadomości adresowych związanych z WebRTC funkcja sendViaSocket (type, message, to) (socket.emit ("webrtc", JSON.stringify ((id: ME, to: to, type: type, data: message )) )));)

2.3. Ustawienia połączenia równorzędnego

Większość dostawców usług internetowych zapewnia translację NAT przez połączenie z Internetem. Dzięki temu bezpośrednie połączenie jest mniej trywialne. Podczas tworzenia połączenia musimy określić listę serwerów STUN i TURN, których przeglądarka będzie próbowała użyć do przechodzenia przez NAT. Wskażemy również kilka dodatkowych opcji połączenia.

Serwer Var = (iceServers: [(url: "stun: 23.21.150.121"), (url: "stun: stun.l.google.com: 19302"), (url: "turn: numb.viagenie.ca", credential: "Twoje hasło jest tutaj", nazwa użytkownika: " [e-mail chroniony]")]); var options = (opcjonalne: [(DtlsSrtpKeyAgreement: true), // wymagane do połączenia między przeglądarkami Chrome i Firefox (RtpDataChannels: true) // wymagane w przeglądarce Firefox do korzystania z interfejsu DataChannels API])

2.4. Podłączanie nowego użytkownika

Gdy do pokoju zostanie dodany nowy peer, serwer wyśle ​​nam wiadomość Nowy... Zgodnie z procedurami obsługi wiadomości powyżej, funkcja zostanie wywołana gniazdoNowyPeer.

rówieśnicy Var = (); function socketNewPeer (data) (peers = (candidateCache:); // tworzenie nowego połączenia var pc = new PeerConnection (serwer, opcje); // inicjalizacja initConnection (pc, data, "offer"); // zapisanie połączenia równorzędnego na liście peers peers.connection = pc; // Utwórz kanał DataChannel, przez który będą wymieniane wiadomości var channel = pc.createDataChannel ("mychannel", ()); channel.owner = data; peers.channel = channel; // Zainstaluj moduł obsługi zdarzeń bindEvents (kanał); // Utwórz ofertę SDP pc.createOffer (funkcja (oferta) (pc.setLocalDescription (oferta);));) function initConnection (pc, id, sdpType) (pc.onicecandidate = function ( zdarzenie) ( if (event.candidate) (// Po znalezieniu nowego kandydata ICE, dodaj go do listy w celu dalszego wysyłania peers.candidateCache.push (event.candidate);) else (// Po zakończeniu wykrywania kandydata, handler zostanie wywołany ponownie, ale bez kandydata // W tym przypadku najpierw wyślemy ofertę SDP do peera, lub Odpowiedź SDP (w zależności od parametru funkcji) ... sendViaSocket (sdpType, pc.localDescription, id); // ... a następnie wszystkie wcześniej znalezione kandydaci ICE dla (var i = 0; i< peers.candidateCache.length; i++) { sendViaSocket("candidate", peers.candidateCache[i], id); } } } pc.oniceconnectionstatechange = function (event) { if (pc.iceConnectionState == "disconnected") { connection_num.innerText = parseInt(connection_num.innerText) - 1; delete peers; } } } function bindEvents (channel) { channel.onopen = function () { connection_num.innerText = parseInt(connection_num.innerText) + 1; }; channel.onmessage = function (e) { chatlog.innerHTML += "

Peer mówi: „+ e.dane +”
"; }; }

2.5. Oferta SDP, odpowiedź SDP, kandydat ICE

Gdy jeden z tych komunikatów zostanie odebrany, wywołujemy odpowiedni program obsługi komunikatów.

Funkcja socketReceived (dane) (var json = JSON.parse (dane); switch (json.type) (przypadek "candidate": remoteCandidateReceived (json.id, json.data); przerwa; przypadek "offer": remoteOfferReceived (json. id, json.data); przerwa; wielkość liter "odpowiedź": remoteAnswerReceived (json.id, json.data); przerwa;))

2.5.0 Oferta SDP
funkcja remoteOfferReceived (id, data) (createConnection (id); var pc = peers.connection; pc.setRemoteDescription (nowy SessionDescription (dane)); pc.createAnswer (funkcja (odpowiedź) (pc.setLocalDescription (odpowiedź);));)); ) function createConnection (id) (if (peers === undefined) (peers = (candidateCache:); var pc = new PeerConnection (serwer, opcje); initConnection (pc, id, "odpowiedź"); peers.connection = pc ; pc.ondatachannel = funkcja (e) (peers.channel = e.channel; peers.channel.owner = id; bindEvents (peers.channel);)))
2.5.1 Odpowiedź SDP
function remoteAnswerReceived (id, data) (var pc = peers.connection; pc.setRemoteDescription (nowy SessionDescription (dane));)
2.5.2 Kandydat ICE
function remoteCandidateReceived (id, data) (createConnection (id); var pc = peers.connection; pc.addIceCandidate (nowy IceCandidate (dane));)
2.6. Wysyłanie wiadomości

Naciskając przycisk Wysłać funkcja nazywa się Wyślij wiadomość... Wszystko, co robi, to przeglądanie listy peerów i próba wysłania wszystkim określonej wiadomości.

DZWON

Są tacy, którzy czytają tę wiadomość przed tobą.
Zapisz się, aby otrzymywać najnowsze artykuły.
E-mail
Nazwa
Nazwisko
Jak chcesz czytać dzwonek?
Bez spamu