ΠŸΡ€Π΅Ρ…Π²ΡŠΡ€Π»ΡΠ½Π΅ Π½Π° многопотрСбитСлска ΠΈΠ³Ρ€Π° ΠΎΡ‚ C++ Π½Π° ΡƒΠ΅Π± с Cheerp, WebRTC ΠΈ Firebase

Π’ΡŠΠ²Π΅Π΄Π΅Π½ΠΈΠ΅

ΠΠ°ΡˆΠ°Ρ‚Π° компания Leaning Technologies ΠΏΡ€Π΅Π΄Π»Π°Π³Π° Π±Π»Π°Π³ΠΎΠ΄Π°Ρ€Π΅Π½ΠΈΠ΅ Π½Π° ΠΏΠΎΡ€Ρ‚Π°Π»Π½ΠΈΡ‚Π΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π·Π° ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π°Π½Π΅ Π½Π° Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΎΠ½Π½ΠΈ настолни прилоТСния Π² ΡƒΠ΅Π±. ΠΠ°ΡˆΠΈΡΡ‚ C++ ΠΊΠΎΠΌΠΏΠΈΠ»Π°Ρ‚ΠΎΡ€ Cheerp Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π° комбинация ΠΎΡ‚ WebAssembly ΠΈ JavaScript, ΠΊΠΎΠ΅Ρ‚ΠΎ осигурява ΠΈ лСсно взаимодСйствиС с Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π°, ΠΈ висока производитСлност.

ΠšΠ°Ρ‚ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° ΠΏΡ€ΠΈΠ»Π°Π³Π°Π½Π΅Ρ‚ΠΎ ΠΌΡƒ Ρ€Π΅ΡˆΠΈΡ…ΠΌΠ΅ Π΄Π° ΠΏΠΎΡ€Ρ‚ΠΈΠΌ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΊΠ° ΠΈΠ³Ρ€Π° Π·Π° ΡƒΠ΅Π± ΠΈ ΠΈΠ·Π±Ρ€Π°Ρ…ΠΌΠ΅ Π·Π° Ρ‚ΠΎΠ²Π° Teeworlds. Teeworlds Π΅ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΠΊΠ° Π΄Π²ΡƒΠΌΠ΅Ρ€Π½Π° Ρ€Π΅Ρ‚Ρ€ΠΎ ΠΈΠ³Ρ€Π° с ΠΌΠ°Π»ΠΊΠΎ, Π½ΠΎ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ общСство ΠΎΡ‚ ΠΈΠ³Ρ€Π°Ρ‡ΠΈ (Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΈ ΠΌΠ΅Π½!). Вя Π΅ ΠΌΠ°Π»ΠΊΠ° ΠΊΠ°ΠΊΡ‚ΠΎ ΠΏΠΎ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ Π½Π° изтСглянС Π½Π° рСсурси, Ρ‚Π°ΠΊΠ° ΠΈ ΠΏΠΎ искания към ЦП ΠΈ GPU β€” идСалният ΠΊΠ°Π½Π΄ΠΈΠ΄Π°Ρ‚.

ΠŸΡ€Π΅Ρ…Π²ΡŠΡ€Π»ΡΠ½Π΅ Π½Π° многопотрСбитСлска ΠΈΠ³Ρ€Π° ΠΎΡ‚ C++ Π½Π° ΡƒΠ΅Π± с Cheerp, WebRTC ΠΈ Firebase
Π Π°Π±ΠΎΡ‚ΠΈ Π² Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π° Teeworlds

Π Π΅ΡˆΠΈΡ…ΠΌΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Ρ‚ΠΎΠ·ΠΈ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚, Π·Π° Π΄Π° СкспСримСнтирамС с ΠΎΠ±Ρ‰ΠΈ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Π·Π° ΠΏΠΎΡ€Ρ‚Π²Π°Π½Π΅ Π½Π° мрСТовия ΠΊΠΎΠ΄ ΠΏΠΎΠ΄ ΡƒΠ΅Π±. ОбикновСно сС изпълнява ΠΏΠΎ слСднитС Π½Π°Ρ‡ΠΈΠ½ΠΈ:

  • XMLHttpRequest/fetch, Π°ΠΊΠΎ ΠΌΡ€Π΅ΠΆΠΎΠ²Π°Ρ‚Π° част Π΅ само ΠΎΡ‚ HTTP заявки, ΠΈΠ»ΠΈ
  • WebSockets.

И Π΄Π²Π°Ρ‚Π° ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π° изискват хостинг Π½Π° ΡΡŠΡ€Π²ΡŠΡ€Π½ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π½Π° страната Π½Π° ΡΡŠΡ€Π²ΡŠΡ€Π° ΠΈ Π½ΠΈΡ‚ΠΎ Π΅Π΄ΠΈΠ½ ΠΎΡ‚ тях Π½Π΅ позволява ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° UDP. Π’ΠΎΠ²Π° Π΅ Π²Π°ΠΆΠ½ΠΎ Π·Π° прилоТСния Π² Ρ€Π΅Π°Π»Π½ΠΎ Π²Ρ€Π΅ΠΌΠ΅, ΠΊΠ°Ρ‚ΠΎ софтуСр Π·Π° Π²ΠΈΠ΄Π΅ΠΎΠΊΠΎΠ½Ρ„Π΅Ρ€Π΅Π½Ρ†ΠΈΠΈ ΠΈ ΠΈΠ³Ρ€ΠΈ, Π·Π°Ρ‰ΠΎΡ‚ΠΎ Π³Π°Ρ€Π°Π½Ρ†ΠΈΠΈΡ‚Π΅ Π·Π° доставка ΠΈ Ρ€Π΅Π΄ Π½Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ ΠΏΠΎ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» TCP ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π½Π°Ρ€ΡƒΡˆΠ°Ρ‚ нискитС закъснСния.

Π‘ΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π° ΠΈ Ρ‚Ρ€Π΅Ρ‚ΠΈ ΠΏΡŠΡ‚ β€” ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΌΡ€Π΅ΠΆΠ°Ρ‚Π° ΠΎΡ‚ Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π°: WebRTC.

RTCDataChannel ΠΏΠΎΠ΄Π΄ΡŠΡ€ΠΆΠ° ΠΊΠ°ΠΊ Π½Π°Π΄Π΅ΠΆΠ΄Π½Π°, Ρ‚Π°ΠΊΠ° ΠΈ Π½Π΅Π½Π°Π΄Π΅ΠΆΠ΄Π½Π° ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅ (Π² послСдния случай сС ΠΎΠΏΠΈΡ‚Π²Π° Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° UDP ΠΊΠ°Ρ‚ΠΎ транспортСн ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»), ΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ ΠΊΠ°ΠΊΡ‚ΠΎ с ΠΎΡ‚Π΄Π°Π»Π΅Ρ‡Π΅Π½ ΡΡŠΡ€Π²ΡŠΡ€, Ρ‚Π°ΠΊΠ° ΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ Π±Ρ€Π°ΡƒΠ·ΡŠΡ€ΠΈ. Π’ΠΎΠ²Π° ΠΎΠ·Π½Π°Ρ‡Π°Π²Π°, Ρ‡Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° ΠΏΠΎΡ€Ρ‚ΠΈΠΌ Π² Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π° всичко ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΈ ΡΡŠΡ€Π²ΡŠΡ€Π½ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚!

Но с Ρ‚ΠΎΠ²Π° ΠΈΠ΄Π²Π° Π΄ΠΎΠΏΡŠΠ»Π½ΠΈΡ‚Π΅Π»Π½Π° трудност: ΠΏΡ€Π΅Π΄ΠΈ Π΄Π²Π°Ρ‚Π° ΠΏΠΈΡ€Π° WebRTC Π΄Π° ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° обмСнят Π΄Π°Π½Π½ΠΈ, Ρ‚Π΅ трябва Π΄Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Ρ‚ ΠΏΡ€Π΅Π· относитСлно слоТна ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° Π½Π° "Ρ€ΡƒΠΊΠΎΠΏΠΎΠΆΠ°Ρ‚ΠΈΠ΅" Π·Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅, която изисква няколко странични субСкта (сигналСн ΡΡŠΡ€Π²ΡŠΡ€ ΠΈ Π΅Π΄ΠΈΠ½ ΠΈΠ»ΠΈ ΠΏΠΎΠ²Π΅Ρ‡Π΅ STUN/TURN).

Π’ идСалния случай Π±ΠΈΡ…ΠΌΠ΅ искали Π΄Π° създадСм ΠΌΡ€Π΅ΠΆΠΎΠ² API, ΠΊΠΎΠΉΡ‚ΠΎ Π² Ρ€Π°ΠΌΠΊΠΈΡ‚Π΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° WebRTC, Π½ΠΎ ΠΊΠΎΠ»ΠΊΠΎΡ‚ΠΎ Π΅ възмоТно ΠΏΠΎ-близък Π΄ΠΎ интСрфСйса Π½Π° UDP Sockets, Π½Π° ΠΊΠΎΠΉΡ‚ΠΎ Π½Π΅ Π΅ Π½ΡƒΠΆΠ½ΠΎ Π΄Π° сС установява Π²Ρ€ΡŠΠ·ΠΊΠ°.

Π’ΠΎΠ²Π° Ρ‰Π΅ Π½ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ прСдимствата Π½Π° WebRTC Π±Π΅Π· нСобходимостта ΠΎΡ‚ Ρ€Π°Π·ΠΊΡ€ΠΈΠ²Π°Π½Π΅ Π½Π° слоТни подробности Π½Π° ΠΊΠΎΠ΄Π° Π½Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ (ΠΊΠΎΠΉΡ‚ΠΎ Π² нашия ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ искахмС Π΄Π° промСнямС възмоТно Π½Π°ΠΉ-ΠΌΠ°Π»ΠΊΠΎ).

МинималСн WebRTC

WebRTC Π΅ Π½Π°Π±ΠΎΡ€ ΠΎΡ‚ API Π² Π±Ρ€Π°ΡƒΠ·Π΅Ρ€ΠΈΡ‚Π΅, ΠΊΠΎΠΉΡ‚ΠΎ осигурява peer-to-peer ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅ Π½Π° Π·Π²ΡƒΠΊ, Π²ΠΈΠ΄Π΅ΠΎ ΠΈ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π½ΠΈ Π΄Π°Π½Π½ΠΈ.

Π‘Π²ΡŠΡ€Π·Π²Π°Π½Π΅Ρ‚ΠΎ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΠΈΡ€ΠΈΡ‚Π΅ сС установява (Π΄ΠΎΡ€ΠΈ ΠΏΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ Π½Π° NAT ΠΎΡ‚ Π΅Π΄Π½Π°Ρ‚Π° ΠΈΠ»ΠΈ ΠΈ Π΄Π²Π΅Ρ‚Π΅ страни) с ΠΏΠΎΠΌΠΎΡ‰Ρ‚Π° Π½Π° ΡΡŠΡ€Π²ΡŠΡ€ΠΈ STUN ΠΈ/ΠΈΠ»ΠΈ TURN Ρ‡Ρ€Π΅Π· ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΡŠΠΌ, Π½Π°Ρ€Π΅Ρ‡Π΅Π½ ICE. ΠŸΠΈΡ€ΠΈΡ‚Π΅ обмСнят информация Π·Π° ICE ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ Π½Π° ΠΊΠ°Π½Π°Π»ΠΈΡ‚Π΅ Ρ‡Ρ€Π΅Π· offer ΠΈ answer ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° SDP.

Π£Π°Ρƒ! Колко ΠΌΠ½ΠΎΠ³ΠΎ ΡΡŠΠΊΡ€Π°Ρ‰Π΅Π½ΠΈΡ навСднъТ. НСка Π½Π°ΠΊΡ€Π°Ρ‚ΠΊΠΎ обясним ΠΊΠ°ΠΊΠ²ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π²Π°Ρ‚ Ρ‚Π΅Π·ΠΈ понятия:

  • Session Traversal Utilities for NAT (STUN) Π΅ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» Π·Π° заобикалянС Π½Π° NAT ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°Π½Π΅ Π½Π° Π΄Π²ΠΎΠΉΠΊΠ° (IP, ΠΏΠΎΡ€Ρ‚) Π·Π° Π΄ΠΈΡ€Π΅ΠΊΡ‚Π΅Π½ ΠΎΠ±ΠΌΠ΅Π½ Π½Π° Π΄Π°Π½Π½ΠΈ с хоста. Ако успСС Π΄Π° изпълни Π·Π°Π΄Π°Ρ‡Π°Ρ‚Π° си, ΠΏΠΈΡ€ΠΈΡ‚Π΅ ΠΌΠΎΠ³Π°Ρ‚ самостоятСлно Π΄Π° обмСнят Π΄Π°Π½Π½ΠΈ ΠΏΠΎΠΌΠ΅ΠΆΠ΄Ρƒ си.
  • Traversal Using Relays around NAT (TURN) ΡΡŠΡ‰ΠΎ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° заобикалянС Π½Π° NAT, Π½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π° Ρ‚ΠΎΠ²Π°, ΠΏΡ€Π΅ΠΏΡ€Π°Ρ‰Π°ΠΉΠΊΠΈ Π΄Π°Π½Π½ΠΈΡ‚Π΅ ΠΏΡ€Π΅Π· прокси, Π²ΠΈΠ΄ΠΈΠΌ ΠΈ Π·Π° Π΄Π²Π°Ρ‚Π° ΠΏΠΈΡ€Π°. Π’ΠΎΠΉ добавя забавянС ΠΈ Π΅ ΠΏΠΎ-скъп ΠΏΡ€ΠΈ изпълнСниС Π² сравнСниС със STUN (Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ сС ΠΏΡ€ΠΈΠ»Π°Π³Π° ΠΏΡ€Π΅Π· цСлия сСанс Π½Π° Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π°), Π½ΠΎ понякога Π΅ СдинствСната Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚.
  • Interactive Connectivity Establishment (ICE) сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° ΠΈΠ·Π±ΠΎΡ€ Π½Π° Π½Π°ΠΉ-добрия възмоТСн Π½Π°Ρ‡ΠΈΠ½ Π·Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅ Π½Π° Π΄Π²Π°Ρ‚Π° ΠΏΠΈΡ€Π° Π½Π° Π±Π°Π·Π°Ρ‚Π° Π½Π° информация, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π° ΠΏΡ€ΠΈ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½Π° ΡΠ²ΡŠΡ€Π·Π°Π½ΠΎΡΡ‚, ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ информация, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π° ΠΎΡ‚ мноТСство ΡΡŠΡ€Π²ΡŠΡ€ΠΈ STUN ΠΈ TURN.
  • Session Description Protocol (SDP) Π΅ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Π·Π° описаниС Π½Π° ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈΡ‚Π΅ Π½Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅Ρ‚ΠΎ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΊΠ°Π½Π΄ΠΈΠ΄Π°Ρ‚ΠΈ ICE, ΠΌΡƒΠ»Ρ‚ΠΈΠΌΠ΅Π΄ΠΈΠΉΠ½ΠΈ ΠΊΠΎΠ΄Π΅Ρ†ΠΈ (Π² случай Π½Π° Π°ΡƒΠ΄ΠΈΠΎ/Π²ΠΈΠ΄Π΅ΠΎΠΊΠ°Π½Π°Π») ΠΈ Ρ‚.Π½. Π•Π΄ΠΈΠ½ ΠΎΡ‚ ΠΏΠΈΡ€ΠΈΡ‚Π΅ ΠΈΠ·ΠΏΡ€Π°Ρ‰Π° SDP Offer (β€žΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅β€œ), Π° вторият отговаря с SDP Answer (β€žΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€β€œ). Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° сС създава ΠΊΠ°Π½Π°Π».

Π—Π° Π΄Π° ΡΡŠΠ·Π΄Π°Π΄Π°Ρ‚ Ρ‚Π°ΠΊΠ°Π²Π° Π²Ρ€ΡŠΠ·ΠΊΠ°, ΠΏΠΈΡ€ΠΈΡ‚Π΅ трябва Π΄Π° ΡΡŠΠ±Π΅Ρ€Π°Ρ‚ информацията, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π° ΠΎΡ‚ ΡΡŠΡ€Π²ΡŠΡ€ΠΈΡ‚Π΅ STUN ΠΈ TURN, ΠΈ Π΄Π° я обмСнят ΠΏΠΎΠΌΠ΅ΠΆΠ΄Ρƒ си.

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΡŠΡ‚ Π΅, Ρ‡Π΅ Ρ‚Π΅ всС ΠΎΡ‰Π΅ нямат Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ Π΄Π° обмСнят Π΄Π°Π½Π½ΠΈ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ Π·Π° ΠΎΠ±ΠΌΠ΅Π½Π° Π½Π° Ρ‚Π΅Π·ΠΈ Π΄Π°Π½Π½ΠΈ трябва Π΄Π° ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π° извънполосСн ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΡŠΠΌ: сигналСн ΡΡŠΡ€Π²ΡŠΡ€.

Бигналният ΡΡŠΡ€Π²ΡŠΡ€ ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС ΠΌΠ½ΠΎΠ³ΠΎ прост, Ρ‚ΡŠΠΉ ΠΊΠ°Ρ‚ΠΎ СдинствСната ΠΌΡƒ Π·Π°Π΄Π°Ρ‡Π° Π΅ Π΄Π° прСнасочва Π΄Π°Π½Π½ΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΏΠΈΡ€ΠΈΡ‚Π΅ Π½Π° Π΅Ρ‚Π°ΠΏΠ° Π½Π° β€žΡ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅β€œ (ΠΊΠ°ΠΊΡ‚ΠΎ Π΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½Π° схСмата ΠΏΠΎ-Π΄ΠΎΠ»Ρƒ).

ΠŸΡ€Π΅Ρ…Π²ΡŠΡ€Π»ΡΠ½Π΅ Π½Π° многопотрСбитСлска ΠΈΠ³Ρ€Π° ΠΎΡ‚ C++ Π½Π° ΡƒΠ΅Π± с Cheerp, WebRTC ΠΈ Firebase
ΠžΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€Π°Π½Π° схСма Π½Π° послСдоватСлността Π½Π° β€žΡ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅β€œ WebRTC

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° ΠΌΡ€Π΅ΠΆΠΎΠ²Π°Ρ‚Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Π½Π° Teeworlds

ΠœΡ€Π΅ΠΆΠΎΠ²Π°Ρ‚Π° Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Π½Π° Teeworlds Π΅ ΠΌΠ½ΠΎΠ³ΠΎ проста:

  • ΠšΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΈΡ‚Π΅ Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° ΠΈ ΡΡŠΡ€Π²ΡŠΡ€Π° са Π΄Π²Π΅ Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΈ.
  • ΠšΠ»ΠΈΠ΅Π½Ρ‚ΠΈΡ‚Π΅ Π²Π»ΠΈΠ·Π°Ρ‚ Π² ΠΈΠ³Ρ€Π°Ρ‚Π°, ΡΠ²ΡŠΡ€Π·Π²Π°ΠΉΠΊΠΈ сС с Π΅Π΄ΠΈΠ½ ΠΎΡ‚ няколко ΡΡŠΡ€Π²ΡŠΡ€Π°, всСки ΠΎΡ‚ ΠΊΠΎΠΈΡ‚ΠΎ хоства само Π΅Π΄Π½Π° ΠΈΠ³Ρ€Π° ΠΏΠΎ Π²Ρ€Π΅ΠΌΠ΅.
  • Цялата ΠΎΠ±ΠΌΠ΅Π½Π½Π° информация Π² ΠΈΠ³Ρ€Π°Ρ‚Π° ΠΏΡ€Π΅ΠΌΠΈΠ½Π°Π²Π° ΠΏΡ€Π΅Π· ΡΡŠΡ€Π²ΡŠΡ€Π°.
  • Π‘ΠΏΠ΅Ρ†ΠΈΠ°Π»Π΅Π½ майстор-ΡΡŠΡ€Π²ΡŠΡ€ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π·Π° ΡΡŠΠ±ΠΈΡ€Π°Π½Π΅ Π½Π° списъка с всички ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈ ΡΡŠΡ€Π²ΡŠΡ€ΠΈ, ΠΊΠΎΠΈΡ‚ΠΎ сС ΠΏΠΎΠΊΠ°Π·Π²Π°Ρ‚ Π² игровия ΠΊΠ»ΠΈΠ΅Π½Ρ‚.

Π‘Π»Π°Π³ΠΎΠ΄Π°Ρ€Π΅Π½ΠΈΠ΅ Π½Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° WebRTC Π·Π° ΠΎΠ±ΠΌΠ΅Π½ Π½Π° Π΄Π°Π½Π½ΠΈ, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° прСмСстим ΡΡŠΡ€Π²ΡŠΡ€Π½ΠΈΡ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ Π½Π° ΠΈΠ³Ρ€Π°Ρ‚Π° Π² Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π°, ΠΊΡŠΠ΄Π΅Ρ‚ΠΎ Π΅ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΡŠΡ‚. Π’ΠΎΠ²Π° Π½ΠΈ прСдоставя чудСсна Π²ΡŠΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚β€¦

Π”Π° сС ΠΎΡ‚ΠΊΠ°ΠΆΠ΅ΠΌ ΠΎΡ‚ ΡΡŠΡ€Π²ΡŠΡ€ΠΈΡ‚Π΅

Липсата Π½Π° ΡΡŠΡ€Π²ΡŠΡ€Π½Π° Π»ΠΎΠ³ΠΈΠΊΠ° ΠΈΠΌΠ° приятно прСдимство: ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Ρ€Π°Π·ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ цялото ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΊΠ°Ρ‚ΠΎ статично ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Π½ΠΈΠ΅ Π½Π° Github Pages ΠΈΠ»ΠΈ Π½Π° собствСно ΠΎΠ±ΠΎΡ€ΡƒΠ΄Π²Π°Π½Π΅ Π·Π°Π΄ Cloudflare, осигурявайки си Ρ‚Π°ΠΊΠ° Π±ΡŠΡ€Π·ΠΈ зарСТдания ΠΈ висок uptime Π±Π΅Π·ΠΏΠ»Π°Ρ‚Π½ΠΎ. Π’ΡΡŠΡ‰Π½ΠΎΡΡ‚, ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° Π·Π°Π±Ρ€Π°Π²ΠΈΠΌ Π·Π° тях, ΠΈ Π°ΠΊΠΎ ΠΈΠΌΠ°ΠΌΠ΅ ΠΊΡŠΡΠΌΠ΅Ρ‚ ΠΈ ΠΈΠ³Ρ€Π°Ρ‚Π° станС популярна, Π½Π΅ Π΅ Π½ΡƒΠΆΠ½ΠΎ Π΄Π° ΠΌΠΎΠ΄Π΅Ρ€Π½ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ инфраструктурата.

Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‚ΠΎΠ²Π°, Π·Π° Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ систСмата, всС ΠΏΠ°ΠΊ Ρ‰Π΅ трябва Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ външна Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°:

  • Π•Π΄ΠΈΠ½ ΠΈΠ»ΠΈ ΠΏΠΎΠ²Π΅Ρ‡Π΅ STUN ΡΡŠΡ€Π²ΡŠΡ€Π°: ΠΈΠΌΠ°ΠΌΠ΅ ΠΈΠ·Π±ΠΎΡ€ ΠΎΡ‚ няколко Π±Π΅Π·ΠΏΠ»Π°Ρ‚Π½ΠΈ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π°.
  • ПонС Π΅Π΄ΠΈΠ½ TURN ΡΡŠΡ€Π²ΡŠΡ€: Ρ‚ΡƒΠΊ няма Π±Π΅Π·ΠΏΠ»Π°Ρ‚Π½ΠΈ ΠΎΠΏΡ†ΠΈΠΈ, Π·Π°Ρ‚ΠΎΠ²Π° ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΠ»ΠΈ Π΄Π° настроим наш, ΠΈΠ»ΠΈ Π΄Π° ΠΏΠ»Π°Ρ‚ΠΈΠΌ Π·Π° услуга. Π—Π° щастиС, ΠΏΠΎ-голямата част ΠΎΡ‚ Π²Ρ€Π΅ΠΌΠ΅Ρ‚ΠΎ Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π° ΠΌΠΎΠΆΠ΅ Π΄Π° бъдС установСна Ρ‡Ρ€Π΅Π· STUN ΡΡŠΡ€Π²ΡŠΡ€ΠΈ (осигурявайки истинско p2p), Π½ΠΎ TURN Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ ΠΊΠ°Ρ‚ΠΎ Ρ€Π΅Π·Π΅Ρ€Π²Π΅Π½ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚.
  • Π‘ΠΈΠ³Π½Π°Π»Π΅Π½ ΡΡŠΡ€Π²ΡŠΡ€: Π·Π° Ρ€Π°Π·Π»ΠΈΠΊΠ° ΠΎΡ‚ Π΄Ρ€ΡƒΠ³ΠΈΡ‚Π΅ Π΄Π²Π° аспСкта, сигнализиранСто Π½Π΅ Π΅ стандартизирано. Π’ΠΎΠ²Π°, Π·Π° ΠΊΠΎΠ΅Ρ‚ΠΎ Π²ΡΡŠΡ‰Π½ΠΎΡΡ‚ Ρ‰Π΅ отговаря сигналният ΡΡŠΡ€Π²ΡŠΡ€, зависи ΠΎΡ‚ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ. Π’ нашия случай, ΠΏΡ€Π΅Π΄ΠΈ Π΄Π° сС установи Π²Ρ€ΡŠΠ·ΠΊΠ°, Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° ΠΎΠ±ΠΌΠ΅Π½ΠΈΠΌ малък ΠΎΠ±Π΅ΠΌ Π΄Π°Π½Π½ΠΈ.
  • ΠœΠ°ΠΉΡΡ‚ΠΎΡ€-ΡΡŠΡ€Π²ΡŠΡ€ Teeworlds: Ρ‚ΠΎΠΉ сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΠΎΡ‚ Π΄Ρ€ΡƒΠ³ΠΈΡ‚Π΅ ΡΡŠΡ€Π²ΡŠΡ€ΠΈ, Π·Π° Π΄Π° увСдомят Π·Π° ΡΡŠΡ‰Π΅ΡΡ‚Π²ΡƒΠ²Π°Π½Π΅Ρ‚ΠΎ си ΠΈ ΠΎΡ‚ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΈΡ‚Π΅ Π΄Π° Ρ‚ΡŠΡ€ΡΡΡ‚ ΠΏΡƒΠ±Π»ΠΈΡ‡Π½ΠΈ ΡΡŠΡ€Π²ΡŠΡ€ΠΈ. Π’ΡŠΠΏΡ€Π΅ΠΊΠΈ Ρ‡Π΅ Π½Π΅ Π΅ Π·Π°Π΄ΡŠΠ»ΠΆΠΈΡ‚Π΅Π»Π΅Π½ (ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΈΡ‚Π΅ Π²ΠΈΠ½Π°Π³ΠΈ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° сС ΡΠ²ΡŠΡ€ΠΆΠ°Ρ‚ Ρ€ΡŠΡ‡Π½ΠΎ с извСстСн ΠΈΠΌ ΡΡŠΡ€Π²ΡŠΡ€), Π±ΠΈ Π±ΠΈΠ»ΠΎ Π΄ΠΎΠ±Ρ€Π΅ Π΄Π° Π³ΠΎ ΠΈΠΌΠ°ΠΌΠ΅, Π·Π° Π΄Π° ΠΌΠΎΠ³Π°Ρ‚ ΠΈΠ³Ρ€Π°Ρ‡ΠΈΡ‚Π΅ Π΄Π° участват Π² ΠΈΠ³Ρ€ΠΈ с ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π½ΠΈ Ρ…ΠΎΡ€Π°.

Π Π΅ΡˆΠΈΡ…ΠΌΠ΅ Π΄Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π±Π΅Π·ΠΏΠ»Π°Ρ‚Π½ΠΈ STUN ΡΡŠΡ€Π²ΡŠΡ€ΠΈ Π½Π° Google, Π° Π΅Π΄ΠΈΠ½ TURN ΡΡŠΡ€Π²ΡŠΡ€ настроихмС сами.

Π—Π° послСднитС Π΄Π²Π΅ Ρ‚ΠΎΡ‡ΠΊΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ…ΠΌΠ΅ Firebase:

  • ΠœΠ°ΠΉΡΡ‚ΠΎΡ€-ΡΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ Teeworlds Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°Π½ ΠΌΠ½ΠΎΠ³ΠΎ просто: ΠΊΠ°Ρ‚ΠΎ списък ΠΎΡ‚ ΠΎΠ±Π΅ΠΊΡ‚ΠΈ, ΡΡŠΠ΄ΡŠΡ€ΠΆΠ°Ρ‰ΠΈ информация (ΠΈΠΌΠ΅, IP, ΠΊΠ°Ρ€Ρ‚Π°, Ρ€Π΅ΠΆΠΈΠΌ ΠΈ Π΄Ρ€.) Π·Π° всСки Π°ΠΊΡ‚ΠΈΠ²Π΅Π½ ΡΡŠΡ€Π²ΡŠΡ€. Π‘ΡŠΡ€Π²ΡŠΡ€ΠΈΡ‚Π΅ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ²Π°Ρ‚ ΠΈ обновяват собствСнитС си ΠΎΠ±Π΅ΠΊΡ‚ΠΈ, Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΈΡ‚Π΅ Π²Π·Π΅ΠΌΠ°Ρ‚ цСлия списък ΠΈ Π³ΠΎ ΠΏΠΎΠΊΠ°Π·Π²Π°Ρ‚ Π½Π° ΠΈΠ³Ρ€Π°Ρ‡Π°. Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° ΠΏΠΎΠΊΠ°Π·Π²Π°ΠΌΠ΅ списъка Π½Π° Π½Π°Ρ‡Π°Π»Π½Π°Ρ‚Π° страница ΠΊΠ°Ρ‚ΠΎ HTML, Π·Π° Π΄Π° ΠΌΠΎΠ³Π°Ρ‚ ΠΈΠ³Ρ€Π°Ρ‡ΠΈΡ‚Π΅ просто Π΄Π° ΠΊΠ»ΠΈΠΊΠ½Π°Ρ‚ Π²ΡŠΡ€Ρ…Ρƒ ΡΡŠΡ€Π²ΡŠΡ€Π° ΠΈ Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ Π΄Π° влязат Π² ΠΈΠ³Ρ€Π°Ρ‚Π°.
  • Бигнализацията Π΅ тясно ΡΠ²ΡŠΡ€Π·Π°Π½Π° с рСализацията Π½Π° сокСтитС, описана Π² слСдващия Ρ€Π°Π·Π΄Π΅Π».

ΠŸΡ€Π΅Ρ…Π²ΡŠΡ€Π»ΡΠ½Π΅ Π½Π° многопотрСбитСлска ΠΈΠ³Ρ€Π° ΠΎΡ‚ C++ Π½Π° ΡƒΠ΅Π± с Cheerp, WebRTC ΠΈ Firebase
Бписък Π½Π° ΡΡŠΡ€Π²ΡŠΡ€ΠΈΡ‚Π΅ Π² ΠΈΠ³Ρ€Π°Ρ‚Π° ΠΈ Π½Π° Π½Π°Ρ‡Π°Π»Π½Π°Ρ‚Π° страница

РСализация Π½Π° сокСтитС

ИскамС Π΄Π° създадСм API, ΠΊΠΎΠΉΡ‚ΠΎ Π΅ възмоТно Π½Π°ΠΉ-Π±Π»ΠΈΠ·ΠΎ Π΄ΠΎ Posix UDP Sockets, Π·Π° Π΄Π° ΠΌΠΈΠ½ΠΈΠΌΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΈΡ‚Π΅ ΠΏΡ€ΠΎΠΌΠ΅Π½ΠΈ.

Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° искамС Π΄Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅ нСобходимия ΠΌΠΈΠ½ΠΈΠΌΡƒΠΌ, Π½ΡƒΠΆΠ΅Π½ Π·Π° прост ΠΎΠ±ΠΌΠ΅Π½ Π½Π° Π΄Π°Π½Π½ΠΈ ΠΏΠΎ ΠΌΡ€Π΅ΠΆΠ°Ρ‚Π°.

НапримСр, Π½Π΅ Π½ΠΈ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° истинска ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΡ: всички ΠΏΠΈΡ€ΠΎΠ²Π΅ сС Π½Π°ΠΌΠΈΡ€Π°Ρ‚ Π² Π΅Π΄Π½Π° β€žΠ²ΠΈΡ€Ρ‚ΡƒΠ°Π»Π½Π° LANβ€œ, ΡΠ²ΡŠΡ€Π·Π°Π½Π° с ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π΅Π½ СкзСмпляр Π½Π° Firebase Π±Π°Π·Π° Π΄Π°Π½Π½ΠΈ.

Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»Π½ΠΎ, Π½Π΅ са Π½ΠΈ Π½ΡƒΠΆΠ½ΠΈ ΡƒΠ½ΠΈΠΊΠ°Π»Π½ΠΈ IP адрСси: Π·Π° ΡƒΠ½ΠΈΠΊΠ°Π»Π½Π° идСнтификация Π½Π° ΠΏΠΈΡ€ΠΎΠ²Π΅Ρ‚Π΅ Π΅ Π΄ΠΎΡΡ‚Π°Ρ‚ΡŠΡ‡Π½ΠΎ Π΄Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ ΡƒΠ½ΠΈΠΊΠ°Π»Π½ΠΈ стойности Π½Π° ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅Ρ‚Π΅ Π½Π° Firebase (Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ Π½Π° Π΄ΠΎΠΌΠ΅ΠΉΠ½ΠΈΡ‚Π΅), ΠΈ всСки ΠΏΠΈΡ€ Π»ΠΎΠΊΠ°Π»Π½ΠΎ Π½Π°Π·Π½Π°Ρ‡Π°Π²Π° β€žΡ„Π°Π»ΡˆΠΈΠ²ΠΈβ€œ IP адрСси Π½Π° всСки ΠΊΠ»ΡŽΡ‡, ΠΊΠΎΠΉΡ‚ΠΎ трябва Π΄Π° сС ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π°. Π’ΠΎΠ²Π° напълно Π½ΠΈ освобоТдава ΠΎΡ‚ нСобходимостта ΠΎΡ‚ Π³Π»ΠΎΠ±Π°Π»Π½ΠΎ Π½Π°Π·Π½Π°Ρ‡Π°Π²Π°Π½Π΅ Π½Π° IP адрСси, ΠΊΠΎΠ΅Ρ‚ΠΎ Π΅ Π½Π΅Ρ‚Ρ€ΠΈΠ²ΠΈΠ°Π»Π½Π° Π·Π°Π΄Π°Ρ‡Π°.

Π•Ρ‚ΠΎ минималният API, ΠΊΠΎΠΉΡ‚ΠΎ трябва Π΄Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΈΡ€Π°ΠΌΠ΅:

// Create and destroy a socket
int socket();
int close(int fd);
// Bind a socket to a port, and publish it on Firebase
int bind(int fd, AddrInfo* addr);
// Send a packet. This lazily create a WebRTC connection to the 
// peer when necessary
int sendto(int fd, uint8_t* buf, int len, const AddrInfo* addr);
// Receive the packets destined to this socket
int recvfrom(int fd, uint8_t* buf, int len, AddrInfo* addr);
// Be notified when new packets arrived
int recvCallback(Callback cb);
// Obtain a local ip address for this peer key
uint32_t resolve(client::String* key);
// Get the peer key for this ip
String* reverseResolve(uint32_t addr);
// Get the local peer key
String* local_key();
// Initialize the library with the given Firebase database and 
// WebRTc connection options
void init(client::FirebaseConfig* fb, client::RTCConfiguration* ice);

API-Ρ‚ΠΎ Π΅ просто ΠΈ наподобява API-Ρ‚ΠΎ Π½Π° Posix Sockets, Π½ΠΎ ΠΈΠΌΠ° няколко Π²Π°ΠΆΠ½ΠΈ Ρ€Π°Π·Π»ΠΈΠΊΠΈ: рСгистриранС Π½Π° ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅, Π½Π°Π·Π½Π°Ρ‡Π°Π²Π°Π½Π΅ Π½Π° Π»ΠΎΠΊΠ°Π»Π½ΠΈ IP адрСси ΠΈ β€žΠ»Π΅Π½ΠΈΠ²ΠΎβ€œ ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅.

РСгистриранС Π½Π° ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅

Π”ΠΎΡ€ΠΈ Π°ΠΊΠΎ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π½Π°Ρ‚Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° Π½Π΅Π±Π»ΠΎΠΊΠΈΡ€Π°Ρ‰ΠΎ въвСТданС-ΠΈΠ·Π²Π΅ΠΆΠ΄Π°Π½Π΅, Π·Π° Π΄Π° Ρ€Π°Π±ΠΎΡ‚ΠΈ Π² ΡƒΠ΅Π± Π±Ρ€Π°ΡƒΠ·ΡŠΡ€, ΠΊΠΎΠ΄ΡŠΡ‚ трябва Π΄Π° бъдС Ρ€Π΅Ρ„Π°ΠΊΡ‚ΠΎΡ€ΠΈΠ·ΠΈΡ€Π°Π½.

ΠŸΡ€ΠΈΡ‡ΠΈΠ½Π°Ρ‚Π° Π·Π° Ρ‚ΠΎΠ²Π° Π΅, Ρ‡Π΅ Ρ†ΠΈΠΊΡŠΠ»ΡŠΡ‚ Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ Π² Π±Ρ€Π°ΡƒΠ·ΡŠΡ€Π° Π΅ скрит ΠΎΡ‚ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠ°Ρ‚Π° (нСзависимо Π΄Π°Π»ΠΈ Π΅ JavaScript ΠΈΠ»ΠΈ WebAssembly).

Π’ Π½Π°Ρ‚ΠΈΠ²Π½Π° срСда ΠΌΠΎΠΆΠ΅ΠΌ Π΄Π° пишСм ΠΊΠΎΠ΄ ΠΏΠΎ слСдния Π½Π°Ρ‡ΠΈΠ½

while(running) {
  select(...); // Ρ‡Π°ΠΊΠ° Π·Π° I/O ΡΡŠΠ±ΠΈΡ‚ΠΈΡ
  while(true) {
    int r = readfrom(...); // ΠΎΠΏΠΈΡ‚Π²Π° сС Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅
    if (r < 0 && errno == EWOULDBLOCK) // няма Π½Π°Π»ΠΈΡ‡Π½ΠΈ Π΄Π°Π½Π½ΠΈ
      break;
    ...
  }
  ...
}

Ако Ρ†ΠΈΠΊΡŠΠ»ΡŠΡ‚ Π½Π° ΡΡŠΠ±ΠΈΡ‚ΠΈΡ Π΅ скрит Π·Π° нас, Ρ‚ΠΎ трябва Π΄Π° Π³ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π°ΠΌΠ΅ Π² Π½Π΅Ρ‰ΠΎ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ:

auto cb = []() { // Ρ‚ΠΎΠ²Π° Ρ‰Π΅ бъдС ΠΈΠ·Π²ΠΈΠΊΠ°Π½ΠΎ, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π½ΠΎΠ²ΠΈ Π΄Π°Π½Π½ΠΈ са Π½Π°Π»ΠΈΡ‡Π½ΠΈ
  while(true) {
    int r = readfrom(...); // ΠΎΠΏΠΈΡ‚Π²Π° сС Π΄Π° ΠΏΡ€ΠΎΡ‡Π΅Ρ‚Π΅
    if (r < 0 && errno == EWOULDBLOCK) // няма Π½Π°Π»ΠΈΡ‡Π½ΠΈ Π΄Π°Π½Π½ΠΈ
      break;
    ...
  }
  ...
};
recvCallback(cb); // рСгистрирайтС ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΡ‚ΠΎ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅

НазначаванС Π½Π° Π»ΠΎΠΊΠ°Π»Π½ΠΈ IP адрСси

Π˜Π΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€ΠΈΡ‚Π΅ Π½Π° Π²ΡŠΠ·Π»ΠΈΡ‚Π΅ Π² Π½Π°ΡˆΠ°Ρ‚Π° β€žΠΌΡ€Π΅ΠΆΠ°β€œ Π½Π΅ са IP адрСси, Π° ΠΊΠ»ΡŽΡ‡ΠΎΠ²Π΅ Π½Π° Firebase (Ρ‚ΠΎΠ²Π° са Π½ΠΈΠ·ΠΎΠ²Π΅, ΠΊΠΎΠΈΡ‚ΠΎ ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π°Ρ‚ Ρ‚Π°ΠΊΠ°: -LmEC50PYZLCiCP-vqde ).

Π’ΠΎΠ²Π° Π΅ ΡƒΠ΄ΠΎΠ±Π½ΠΎ, Π·Π°Ρ‰ΠΎΡ‚ΠΎ Π½Π΅ Π½ΠΈ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΡŠΠΌ Π·Π° Π½Π°Π·Π½Π°Ρ‡Π°Π²Π°Π½Π΅ Π½Π° IP адрСси ΠΈ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° тяхната уникалност (ΠΊΠ°ΠΊΡ‚ΠΎ ΠΈ тяхното ΠΈΠ·Ρ…Π²ΡŠΡ€Π»ΡΠ½Π΅ слСд ΠΎΡ‚ΠΊΠ°Π· Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°), Π½ΠΎ чСсто Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° сС ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΡ†ΠΈΡ€Π°Ρ‚ пирс ΠΏΠΎ числовата стойност.

Π’ΠΎΡ‡Π½ΠΎ Π·Π° Ρ‚ΠΎΠ²Π° сС ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈΡ‚Π΅ resolve ΠΈ reverseResolve: ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ ΠΏΠΎ някакъв Π½Π°Ρ‡ΠΈΠ½ ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π° стрингова стойност Π½Π° ΠΊΠ»ΡŽΡ‡Π° (Ρ‡Ρ€Π΅Π· потрСбитСлски Π²Ρ…ΠΎΠ΄ ΠΈΠ»ΠΈ Ρ‡Ρ€Π΅Π· мастСр-ΡΡŠΡ€Π²ΡŠΡ€) ΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° я ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ²Π° Π² IP адрСс Π·Π° Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ½Π° ΡƒΠΏΠΎΡ‚Ρ€Π΅Π±Π°. ΠžΡΡ‚Π°Π½Π°Π»Π°Ρ‚Π° част ΠΎΡ‚ API ΡΡŠΡ‰ΠΎ ΠΏΠΎ простота ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π° вмСсто стринг Ρ‚ΠΎΠ²Π° Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.

Π’ΠΎΠ²Π° Π΅ ΠΏΠΎΠ΄ΠΎΠ±Π½ΠΎ Π½Π° DNS Ρ‚ΡŠΡ€ΡΠ΅Π½Π΅, само Ρ‡Π΅ сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Π»ΠΎΠΊΠ°Π»Π½ΠΎ ΠΎΡ‚ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°.

ВоСст IP адрСситС Π½Π΅ ΠΌΠΎΠ³Π°Ρ‚ Π΄Π° Π±ΡŠΠ΄Π°Ρ‚ ΠΎΠ±Ρ‰ΠΈ Π·Π° Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΠΈ, ΠΈ Π°ΠΊΠΎ Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ някакъв Π³Π»ΠΎΠ±Π°Π»Π΅Π½ ΠΈΠ΄Π΅Π½Ρ‚ΠΈΡ„ΠΈΠΊΠ°Ρ‚ΠΎΡ€, Ρ‚ΠΎΠΉ трябва Π΄Π° бъдС Π³Π΅Π½Π΅Ρ€ΠΈΡ€Π°Π½ ΠΏΠΎ Π΄Ρ€ΡƒΠ³ Π½Π°Ρ‡ΠΈΠ½.

Π›Π΅Π½ΠΈΠ²Π° Π²Ρ€ΡŠΠ·ΠΊΠ°

UDP Π½Π΅ изисква ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅, Π½ΠΎ, ΠΊΠ°ΠΊΡ‚ΠΎ видяхмС, ΠΏΡ€Π΅Π΄ΠΈ Π΄Π° Π·Π°ΠΏΠΎΡ‡Π½Π΅ ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° Π΄Π°Π½Π½ΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ Π΄Π²Π° ΠΏΠΈΡ€Π°, WebRTC изисква дълъг процСс Π½Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅.

Ако искамС Π΄Π° осигурим ΡΡŠΡ‰ΠΎΡ‚ΠΎ Π½ΠΈΠ²ΠΎ Π½Π° абстракция, (sendto/recvfrom с ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»Π½ΠΈ ΠΏΠΈΡ€Π° Π±Π΅Π· ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»Π½ΠΎ ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅), Ρ‚ΠΎ трябва Π΄Π° ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π°ΠΌΠ΅ β€žΠ»Π΅Π½ΠΈΠ²ΠΎβ€œ (ΠΎΡ‚Π»ΠΎΠΆΠ΅Π½ΠΎ) ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅ Π² API.

Π•Ρ‚ΠΎ ΠΊΠ°ΠΊΠ²ΠΎ сС случва ΠΏΡ€ΠΈ ΠΎΠ±ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ ΠΎΠ±ΠΌΠ΅Π½ Π½Π° Π΄Π°Π½Π½ΠΈ ΠΌΠ΅ΠΆΠ΄Ρƒ β€žΡΡŠΡ€Π²Π΅Ρ€Π°β€œ ΠΈ β€žΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°β€œ ΠΏΡ€ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½Π΅ Π½Π° UDP, ΠΈ ΠΊΠ°ΠΊΠ²ΠΎ трябва Π΄Π° ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Π½Π°ΡˆΠ°Ρ‚Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ°:

  • Π‘ΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ ΠΈΠ·Π²ΠΈΠΊΠ²Π° bind(), Π·Π° Π΄Π° ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠΈΡ€Π° ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Π°Ρ‚Π° систСма, Ρ‡Π΅ иска Π΄Π° ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ Π½Π° ΡƒΠΊΠ°Π·Π°Π½ ΠΏΠΎΡ€Ρ‚.

ВмСсто Ρ‚ΠΎΠ²Π° ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ²Π°ΠΌΠ΅ ΠΎΡ‚ΠΊΡ€ΠΈΡ‚ ΠΏΠΎΡ€Ρ‚ Π² Firebase ΠΏΠΎΠ΄ ΠΊΠ»ΡŽΡ‡Π° Π½Π° ΡΡŠΡ€Π²Π΅Ρ€Π° ΠΈ Ρ‰Π΅ ΡΠ»ΡƒΡˆΠ°ΠΌΠ΅ ΡΡŠΠ±ΠΈΡ‚ΠΈΡ Π² Π½Π΅Π³ΠΎΠ²ΠΎΡ‚ΠΎ ΠΏΠΎΠ΄Π΄ΡŠΡ€Π²ΠΎ.

  • Π‘ΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ ΠΈΠ·Π²ΠΈΠΊΠ²Π° recvfrom(), ΠΏΡ€ΠΈΠ΅ΠΌΠ°Ρ‰ΠΈ Π½Π° Ρ‚ΠΎΠ·ΠΈ ΠΏΠΎΡ€Ρ‚ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ, ΠΏΠΎΡΡ‚ΡŠΠΏΠ²Π°Ρ‰ΠΈ ΠΎΡ‚ всякакви хостовС.

Π’ нашия случай трябва Π΄Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ входящата опашка ΠΎΡ‚ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ, ΠΈΠ·ΠΏΡ€Π°Ρ‚Π΅Π½ΠΈ Π½Π° Ρ‚ΠΎΠ·ΠΈ ΠΏΠΎΡ€Ρ‚.

ВсСки ΠΏΠΎΡ€Ρ‚ ΠΈΠΌΠ° собствСна опашка, ΠΈ добавямС Π² Π½Π°Ρ‡Π°Π»ΠΎΡ‚ΠΎ Π½Π° Π΄Π°Ρ‚Π°Π³Ρ€Π°ΠΌΠΈΡ‚Π΅ WebRTC ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π½ΠΈΡ‚Π΅ ΠΈ ΠΊΡ€Π°ΠΉΠ½ΠΈΡ‚Π΅ ΠΏΠΎΡ€Ρ‚ΠΎΠ²Π΅, Π·Π° Π΄Π° Π·Π½Π°Π΅ΠΌ Π² коя опашка Π΄Π° прСнасочим новия ΠΏΠ°ΠΊΠ΅Ρ‚, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Ρ‚ΠΎΠΉ ΠΏΠΎΡΡ‚ΡŠΠΏΠΈ.

Π˜Π·Π²ΠΈΠΊΠ²Π°Π½Π΅Ρ‚ΠΎ Π½Π΅ Π±Π»ΠΎΠΊΠΈΡ€Π°, Ρ‚Π°ΠΊΠ° Ρ‡Π΅ Π°ΠΊΠΎ няма ΠΏΠ°ΠΊΠ΅Ρ‚ΠΈ, просто Π²Ρ€ΡŠΡ‰Π°ΠΌΠ΅ -1 ΠΈ Π·Π°Π΄Π°Π²Π°ΠΌΠ΅ errno=EWOULDBLOCK.

  • ΠšΠ»ΠΈΠ΅Π½Ρ‚ΡŠΡ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π° Ρ‡Ρ€Π΅Π· външни срСдства IP ΠΈ ΠΏΠΎΡ€Ρ‚Π° Π½Π° ΡΡŠΡ€Π²Π΅Ρ€Π° ΠΈ ΠΈΠ·Π²ΠΈΠΊΠ²Π° sendto(). Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° Π² Ρ‚ΠΎΠ·ΠΈ ΠΌΠΎΠΌΠ΅Π½Ρ‚ сС ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π° Π²ΡŠΡ‚Ρ€Π΅ΡˆΠ½ΠΎ ΠΈΠ·Π²ΠΈΠΊΠ²Π°Π½Π΅, Π·Π°Ρ‚ΠΎΠ²Π° послСдващото bind()Ρ‰Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈ ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€ Π±Π΅Π· явното ΠΈΠ·Π²ΡŠΡ€ΡˆΠ²Π°Π½Π΅ Π½Π° bind. recvfrom() Ρ‰Π΅ ΠΏΠΎΠ»ΡƒΡ‡ΠΈ ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€ Π±Π΅Π· явното изпълнСниС Π½Π° bind.

Π’ нашия случай ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΡŠΡ‚ ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π° стрингов ΠΊΠ»ΡŽΡ‡ ΠΈ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° функцията resolve() Π·Π° ΠΏΠΎΠ»ΡƒΡ‡Π°Π²Π°Π½Π΅ Π½Π° IP адрСс.

Π’ Ρ‚ΠΎΠ·ΠΈ Π΅Ρ‚Π°ΠΏ Π·Π°ΠΏΠΎΡ‡Π²Π°ΠΌΠ΅ "Ρ€ΡŠΠΊΠΎΡΡ‚ΠΈΡΠΊΠ°Π½Π΅Ρ‚ΠΎ" Π½Π° WebRTC, Π°ΠΊΠΎ Π΄Π²Π°Ρ‚Π° ΠΏΠΈΡ€Π° всС ΠΎΡ‰Π΅ Π½Π΅ са ΡΠ²ΡŠΡ€Π·Π°Π½ΠΈ ΠΏΠΎΠΌΠ΅ΠΆΠ΄Ρƒ си. Π‘Π²ΡŠΡ€Π·Π²Π°Π½ΠΈΡΡ‚Π° към Ρ€Π°Π·Π»ΠΈΡ‡Π½ΠΈ ΠΏΠΎΡ€Ρ‚ΠΎΠ²Π΅ Π½Π° Π΅Π΄ΠΈΠ½ ΠΈ ΡΡŠΡ‰ ΠΏΠΈΡ€ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Ρ‚ Π΅Π΄ΠΈΠ½ ΠΈ ΡΡŠΡ‰ DataChannel WebRTC.

Π‘ΡŠΡ‰ΠΎ Ρ‚Π°ΠΊΠ° изпълнявамС ΠΈΠ½Π΄ΠΈΡ€Π΅ΠΊΡ‚Π½ΠΎ bind(), Π·Π° Π΄Π° ΠΌΠΎΠΆΠ΅ ΡΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ Π΄Π° Π²ΡŠΠ·ΡΡ‚Π°Π½ΠΎΠ²ΠΈ Π²Ρ€ΡŠΠ·ΠΊΠ°Ρ‚Π° Π² слСдващия sendto() Ссли тя ΠΏΠΎ някаква ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π° Π΅ Π·Π°Ρ‚Π²ΠΎΡ€Π΅Π½Π°.

Π‘ΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ сС увСдомява Π·Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅Ρ‚ΠΎ Π½Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π°, ΠΊΠΎΠ³Π°Ρ‚ΠΎ ΠΊΠ»ΠΈΠ΅Π½Ρ‚ΡŠΡ‚ запишС своя SDP ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ΄ информацията Π·Π° ΠΏΠΎΡ€Ρ‚Π° Π½Π° ΡΡŠΡ€Π²ΡŠΡ€Π° Π² Firebase ΠΈ ΡΡŠΡ€Π²ΡŠΡ€ΡŠΡ‚ Ρ‚Π°ΠΌ отговаря със своСто Π²ΡŠΠ·Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅.

На ΠΏΠΎΠΊΠ°Π·Π°Π½Π°Ρ‚Π° ΠΏΠΎ-Π΄ΠΎΠ»Ρƒ схСма Π΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ Π½Π° ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΡ Π·Π° схСмата Π½Π° сокСти ΠΈ ΠΏΡ€Π΅Π΄Π°Π²Π°Π½Π΅Ρ‚ΠΎ ΠΎΡ‚ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° Π½Π° ΠΏΡŠΡ€Π²ΠΎΡ‚ΠΎ ΡΡŠΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ Π΄ΠΎ ΡΡŠΡ€Π²ΡŠΡ€Π°:

ΠŸΡ€Π΅Ρ…Π²ΡŠΡ€Π»ΡΠ½Π΅ Π½Π° многопотрСбитСлска ΠΈΠ³Ρ€Π° ΠΎΡ‚ C++ Π½Π° ΡƒΠ΅Π± с Cheerp, WebRTC ΠΈ Firebase
Пълна схСма Π½Π° Π΅Ρ‚Π°ΠΏΠ° Π½Π° ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΊΠ»ΠΈΠ΅Π½Ρ‚Π° ΠΈ ΡΡŠΡ€Π²ΡŠΡ€Π°

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Ако стС ΠΏΡ€ΠΎΡ‡Π΅Π»ΠΈ Π΄ΠΎ края, вСроятно Π²ΠΈ Π΅ интСрСсно Π΄Π° Π²ΠΈΠ΄ΠΈΡ‚Π΅ тСорията Π² дСйствиС. ΠœΠΎΠΆΠ΅Ρ‚Π΅ Π΄Π° ΠΈΠ³Ρ€Π°Π΅Ρ‚Π΅ Π½Π° teeworlds.leaningtech.com, ΠΎΠΏΠΈΡ‚Π°ΠΉΡ‚Π΅!


ΠŸΡ€ΠΈΡΡ‚Π΅Π»ΡΠΊΠ° ΠΈΠ³Ρ€Π° ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΊΠΎΠ»Π΅Π³ΠΈ

ΠšΠΎΠ΄ΡŠΡ‚ Π½Π° ΠΌΡ€Π΅ΠΆΠΎΠ²Π°Ρ‚Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Π΅ свободно Π΄ΠΎΡΡ‚ΡŠΠΏΠ΅Π½ Π½Π° Github. ΠŸΡ€ΠΈΡΡŠΠ΅Π΄ΠΈΠ½Π΅Ρ‚Π΅ сС към ΠΎΠ±Ρ‰ΡƒΠ²Π°Π½Π΅Ρ‚ΠΎ Π² нашия ΠΊΠ°Π½Π°Π» Π² Gitter!

Π˜Π·Ρ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com

ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ πŸ”₯ ΠšΡƒΠΏΠ΅Ρ‚Π΅ Π½Π°Π΄Π΅ΠΆΠ΄Π΅Π½ хостинг Π·Π° сайтовС с Π·Π°Ρ‰ΠΈΡ‚Π° ΠΎΡ‚ DDoS, VPS VDS ΡΡŠΡ€Π²ΡŠΡ€ΠΈ | ProHoster