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

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

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

ΠšΠ°Ρ‚ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ Π·Π° Π½Π΅Π³ΠΎΠ²ΠΎΡ‚ΠΎ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Ρ€Π΅ΡˆΠΈΡ…ΠΌΠ΅ Π΄Π° ΠΏΠΎΡ€Ρ‚Π²Π°ΠΌΠ΅ Π·Π° ΡƒΠ΅Π± ΠΌΠ½ΠΎΠ³ΠΎΠΏΠ»Π΅ΠΉΡŠΡ€ ΠΈΠ³Ρ€Π° ΠΈ ΠΈΠ·Π±Ρ€Π°Ρ…ΠΌΠ΅ Π·Π° Ρ‚ΠΎΠ²Π° Teeworlds. Teeworlds Π΅ ΠΌΠ½ΠΎΠ³ΠΎΠΏΠ»Π΅ΠΉΡŠΡ€ Π΄Π²ΡƒΠΌΠ΅Ρ€Π½Π° Ρ€Π΅Ρ‚Ρ€ΠΎ ΠΈΠ³Ρ€Π° с ΠΌΠ°Π»ΠΊΠΎ, Π½ΠΎ Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ общСство ΠΎΡ‚ ΠΈΠ³Ρ€Π°Ρ‡ΠΈ (Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»Π½ΠΎ ΠΈ Π°Π·!). Вя Π΅ ΠΌΠ°Π»ΠΊΠ° ΠΊΠ°ΠΊΡ‚ΠΎ ΠΏΠΎ ΠΎΡ‚Π½ΠΎΡˆΠ΅Π½ΠΈΠ΅ Π½Π° ΠΈΠ·Ρ‚Π΅Π³Π»Π΅Π½ΠΈΡ‚Π΅ рСсурси, Ρ‚Π°ΠΊΠ° ΠΈ ΠΏΠΎ изискванията към CPU ΠΈ 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 ΠΈ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΈ Π½Π° ΠΊΠ°Π½Π°Π»ΠΈΡ‚Π΅ Ρ‡Ρ€Π΅Π· ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅Ρ‚ΠΎ ΠΈ ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€Π° Π½Π° 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 ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π° другият отговаря със SDP ΠΎΡ‚Π³ΠΎΠ²ΠΎΡ€. Π‘Π»Π΅Π΄ Ρ‚ΠΎΠ²Π° сС създава ΠΊΠ°Π½Π°Π».

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

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

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

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

ΠŸΡ€Π΅Π³Π»Π΅Π΄ Π½Π° мрСТовия ΠΌΠΎΠ΄Π΅Π» Teeworlds

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

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

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

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

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

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

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

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

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

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

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

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

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

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

НапримСр, Π½Π΅ Π½ΠΈ трябва истинска ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΡ: всички ΠΏΠΈΡ€ΠΎΠ²Π΅ са Π² Π΅Π΄Π½Π° "Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»Π½Π° 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 сокСти, Π½ΠΎ ΠΈΠΌΠ° няколко Π²Π°ΠΆΠ½ΠΈ различия: рСгистрация Π½Π° ΠΊΠΎΠ»Π±Π΅ΠΊ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π½Π°Π·Π½Π°Ρ‡Π°Π²Π°Π½Π΅ Π½Π° Π»ΠΎΠΊΠ°Π»Π½ΠΈ IP адрСси ΠΈ "Π»Π΅Π½ΠΈΠ²ΠΎ" ΡΠ²ΡŠΡ€Π·Π²Π°Π½Π΅.

РСгистрация Π½Π° ΠΊΠΎΠ»Π±Π΅ΠΊ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ

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

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

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

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

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

auto cb = []() { // Ρ‚ΠΎΠ²Π° Ρ‰Π΅ бъдС ΠΈΠ·Π²ΠΈΠΊΠ°Π½ΠΎ, ΠΊΠΎΠ³Π°Ρ‚ΠΎ Π½ΠΎΠ²ΠΈ Π΄Π°Π½Π½ΠΈ са Π½Π°Π»ΠΈΡ‡Π½ΠΈ
  Π΄ΠΎΠΊΠ°Ρ‚ΠΎ(истина) {
    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(), Ρ‚Π°ΠΊΠ° Ρ‡Π΅ послСдващият 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