РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚ Π΄Π°Π²Π½ΠΎ измСнился. Один ΠΈΠ· основных ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΎΠ² Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚Π° – UDP ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ прилоТСниям Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для доставки Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌ ΠΈ ΡˆΠΈΡ€ΠΎΠΊΠΎΠ²Π΅Ρ‰Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… рассылок, Π½ΠΎ ΠΈ для обСспСчСния Β«peer-to-peerΒ» соСдинСний ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ сСти. Π’Π²ΠΈΠ΄Ρƒ своСго простого устройства, Ρƒ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° появилось мноТСство Π½Π΅ Π·Π°ΠΏΠ»Π°Π½ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… Ρ€Π°Π½Π΅Π΅ способов примСнСния, ΠΏΡ€Π°Π²Π΄Π°, нСдостатки ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ отсутствиС Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ доставки, Π½ΠΈΠΊΡƒΠ΄Π° ΠΏΡ€ΠΈ этом Π½Π΅ исчСзли. Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ описываСтся рСализация ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ доставки ΠΏΠΎΠ²Π΅Ρ€Ρ… UDP.
Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠ°Π½ΠΈΠ΅:ВступлСниС
ВрСбования ΠΊ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Ρƒ
Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Reliable UDP
ΠžΠ±Ρ‰ΠΈΠ΅ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°
Π’Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρ‹ ΠΈ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Ρ‹ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°
Π”ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ° состояний ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Reliable UDP
Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. Π‘Π»ΠΎΠΊ управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ
Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. Бостояния

Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈ установлСниС соСдинСний
Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. Π—Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ соСдинСния ΠΏΠΎ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρƒ
Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. ВосстановлСниС ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ…
API Reliable UDP
Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅
ΠŸΠΎΠ»Π΅Π·Π½Ρ‹Π΅ ссылки ΠΈ ΡΡ‚Π°Ρ‚ΡŒΠΈ

ВступлСниС

ΠŸΠ΅Ρ€Π²ΠΎΠ½Π°Ρ‡Π°Π»ΡŒΠ½Π°Ρ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚Π° ΠΏΠΎΠ΄Ρ€Π°Π·ΡƒΠΌΠ΅Π²Π°Π»Π° ΠΎΠ΄Π½ΠΎΡ€ΠΎΠ΄Π½ΠΎΠ΅ адрСсноС пространство, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ·Π΅Π» ΠΈΠΌΠ΅Π» Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΈ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ IP адрСс, ΠΈ ΠΌΠΎΠ³ Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ ΠΎΠ±Ρ‰Π°Ρ‚ΡŒΡΡ с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ ΡƒΠ·Π»Π°ΠΌΠΈ. БСйчас Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚, ΠΏΠΎ Ρ„Π°ΠΊΡ‚Ρƒ, ΠΈΠΌΠ΅Π΅Ρ‚ Π΄Ρ€ΡƒΠ³ΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ – ΠΎΠ΄Π½Ρƒ ΠΎΠ±Π»Π°ΡΡ‚ΡŒ Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹Ρ… IP адрСсов ΠΈ мноТСство областСй с частным адрСсами, скрытых Π·Π° NAT устройствами.Π’ Ρ‚Π°ΠΊΠΎΠΉ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π΅, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ устройства находящиСся Π² глобальном адрСсном пространствС ΠΌΠΎΠ³ΡƒΡ‚ с Π»Π΅Π³ΠΊΠΎΡΡ‚ΡŒΡŽ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ с ΠΊΠ΅ΠΌ-Π»ΠΈΠ±ΠΎ Π² сСти, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΈΠΌΠ΅ΡŽΡ‚ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ, Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌΡ‹ΠΉ IP адрСс. Π£Π·Π΅Π», находящийся Π² частной сСти, ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ΅Π΄ΠΈΠ½ΡΡ‚ΡŒΡΡ с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ ΡƒΠ·Π»Π°ΠΌΠΈ Π² этой ΠΆΠ΅ сСти, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½ΡΡ‚ΡŒΡΡ с Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ, Ρ…ΠΎΡ€ΠΎΡˆΠΎ извСстными ΡƒΠ·Π»Π°ΠΌΠΈ Π² глобальном адрСсном пространствС. Π’Π°ΠΊΠΎΠ΅ взаимодСйствиС достигаСтся Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΎΠΌ благодаря ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡƒ прСобразования сСтСвых адрСсов. NAT устройства, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Wi-Fi ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ‚ΠΎΡ€Ρ‹, ΡΠΎΠ·Π΄Π°ΡŽΡ‚ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ записи Π² Ρ‚Π°Π±Π»ΠΈΡ†Π°Ρ… трансляций для исходящих соСдинСний ΠΈ ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΡƒΡŽΡ‚ IP адрСса ΠΈ Π½ΠΎΠΌΠ΅Ρ€Π° ΠΏΠΎΡ€Ρ‚ΠΎΠ² Π² ΠΏΠ°ΠΊΠ΅Ρ‚Π°Ρ…. Π­Ρ‚ΠΎ позволяСт ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ ΠΈΠ· частной сСти исходящСС соСдинСниС с ΡƒΠ·Π»Π°ΠΌΠΈ Π² глобальном адрСсном пространствС. Но Π² Ρ‚ΠΎ ΠΆΠ΅ врСмя, NAT устройства ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π±Π»ΠΎΠΊΠΈΡ€ΡƒΡŽΡ‚ вСсь входящий Ρ‚Ρ€Π°Ρ„ΠΈΠΊ, Ссли Π½Π΅ установлСны ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΏΡ€Π°Π²ΠΈΠ»Π° для входящих соСдинСний.

Вакая Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π° Π˜Π½Ρ‚Π΅Ρ€Π½Π΅Ρ‚Π° достаточно ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½Π° для ΠΊΠ»ΠΈΠ΅Π½Ρ‚-сСрвСрного взаимодСйствия, ΠΊΠΎΠ³Π΄Π° ΠΊΠ»ΠΈΠ΅Π½Ρ‚Ρ‹ ΠΌΠΎΠ³ΡƒΡ‚ Π½Π°Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ Π² частных сСтях, Π° сСрвСры имСю Π³Π»ΠΎΠ±Π°Π»ΡŒΠ½Ρ‹ΠΉ адрСс. Но ΠΎΠ½Π° создаСт трудности для прямого соСдинСния Π΄Π²ΡƒΡ… ΡƒΠ·Π»ΠΎΠ² ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ частными сСтями. ΠŸΡ€ΡΠΌΠΎΠ΅ соСдинСниС Π΄Π²ΡƒΡ… ΡƒΠ·Π»ΠΎΠ² Π²Π°ΠΆΠ½ΠΎ для Β«peer-to-peerΒ» ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° голоса (Skype), ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎΠ³ΠΎ доступа ΠΊ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Ρƒ (TeamViewer), ΠΈΠ»ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ ΠΈΠ³Ρ€Ρ‹.

Один ΠΈΠ· Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ эффСктивных ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² для установлСния peer-to-peer соСдинСния ΠΌΠ΅ΠΆΠ΄Ρƒ устройствами находящимися Π² Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… частных сСтях называСтся Β«hole punchingΒ». Π­Ρ‚ΠΎΡ‚ Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ° Ρ‡Π°Ρ‰Π΅ всСго ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ с прилоТСниями Π½Π° основС UDP ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°.

Но Ссли Π²Π°ΡˆΠ΅ΠΌΡƒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ трСбуСтся гарантированная доставка Π΄Π°Π½Π½Ρ‹Ρ…, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π²Ρ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅Ρ‚Π΅ Ρ„Π°ΠΉΠ»Ρ‹ ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΊΠΎΠΌΠΏΡŒΡŽΡ‚Π΅Ρ€Π°ΠΌΠΈ, Ρ‚ΠΎ ΠΏΡ€ΠΈ использовании UDP появится мноТСство трудностСй, связанных с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ UDP Π½Π΅ являСтся ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΎΠΌ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ доставки ΠΈ Π½Π΅ обСспСчиваСт доставку ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΏΠΎ порядку, Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ TCP ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°.

Π’ Ρ‚Π°ΠΊΠΎΠΌ случаС, для обСспСчСния Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ доставки ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², трСбуСтся Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ΠΏΡ€ΠΈΠΊΠ»Π°Π΄Π½ΠΎΠ³ΠΎ уровня, ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‰ΠΈΠΉ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰ΠΈΠΉ ΠΏΠΎΠ²Π΅Ρ€Ρ… UDP.

Π‘Ρ€Π°Π·Ρƒ Ρ…ΠΎΡ‡Ρƒ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ сущСствуСт Ρ‚Π΅Ρ…Π½ΠΈΠΊΠ° TCP hole punching, для установлСния TCP соСдинСний ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ Π² Ρ€Π°Π·Π½Ρ‹Ρ… частных сСтях, Π½ΠΎ Π²Π²ΠΈΠ΄Ρƒ отсутствия ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠΈ Π΅Ρ‘ ΠΌΠ½ΠΎΠ³ΠΈΠΌΠΈ NAT устройствами ΠΎΠ½Π° ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ Π½Π΅ рассматриваСтся ΠΊΠ°ΠΊ основной способ соСдинСния Ρ‚Π°ΠΊΠΈΡ… ΡƒΠ·Π»ΠΎΠ².

Π”Π°Π»Π΅Π΅ Π² этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ я Π±ΡƒΠ΄Ρƒ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ доставки. РСализация Ρ‚Π΅Ρ…Π½ΠΈΠΊΠΈ UDP hole punching Π±ΡƒΠ΄Π΅Ρ‚ описана Π² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… ΡΡ‚Π°Ρ‚ΡŒΡΡ….

ВрСбования ΠΊ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Ρƒ

  1. НадСТная доставка ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², рСализованная Ρ‡Π΅Ρ€Π΅Π· ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ ΠΏΠΎΠ»ΠΎΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠΉ связи (Ρ‚Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΡ‹ΠΉ positive acknowledgment )
  2. ΠΠ΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ эффСктивной ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π±ΠΎΠ»ΡŒΡˆΠΈΡ… Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‚.Π΅. ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΠ·Π±Π΅Π³Π°Ρ‚ΡŒ Π»ΠΈΡˆΠ½ΠΈΡ… рСтрансляций ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²
  3. Π”ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΎΡ‚ΠΌΠ΅Π½Ρ‹ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° подтвСрТдСния доставки ( Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ «чистый» UDP ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»)
  4. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠ³ΠΎ Ρ€Π΅ΠΆΠΈΠΌΠ°, с ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ сообщСния
  5. Π‘Π°Π·ΠΎΠ²ΠΎΠΉ Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅ΠΉ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Ρƒ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±Ρ‹Ρ‚ΡŒ сообщСниС

Π­Ρ‚ΠΈ трСбования Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΎΠΌ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡŽΡ‚ с трСбованиями ΠΊ Reliable Data Protocol, описанными Π² rfc 908 ΠΈ rfc 1151, ΠΈ я основывался Π½Π° этих стандартах ΠΏΡ€ΠΈ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°.

Для понимания Π΄Π°Π½Π½Ρ‹Ρ… Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΠΉ, Π΄Π°Π²Π°ΠΉΡ‚Π΅ рассмотрим Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠ΅ΠΆΠ΄Ρƒ двумя ΡƒΠ·Π»Π°ΠΌΠΈ сСти ΠΏΠΎ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°ΠΌ TCP ΠΈ UDP. ΠŸΡƒΡΡ‚ΡŒ Π² ΠΎΠ±ΠΎΠΈΡ… случаях Ρƒ нас Π±ΡƒΠ΄Π΅Ρ‚ потСрян ΠΎΠ΄ΠΈΠ½ ΠΏΠ°ΠΊΠ΅Ρ‚.
ΠŸΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Π½Π΅ΠΈΠ½Ρ‚Π΅Ρ€Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎ TCP:РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Как Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΡ‹, Π² случаС ΠΏΠΎΡ‚Π΅Ρ€ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², TCP ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ потСрянный ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΈ сообщит ΠΎΠ± этом ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŽ, запросив Π½ΠΎΠΌΠ΅Ρ€ потСрянного сСгмСнта.
ΠŸΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Ρƒ UDP:РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

UDP Π½Π΅ ΠΏΡ€Π΅Π΄ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π½ΠΈΠΊΠ°ΠΊΠΈΡ… шагов ΠΏΠΎ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΡŽ ΠΏΠΎΡ‚Π΅Ρ€ΡŒ. ΠšΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ ошибок ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π² UDP ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π΅ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ возлагаСтся Π½Π° ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅.

ΠžΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ошибок Π² TCP ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π΅ достигаСтся благодаря установкС соСдинСния с ΠΊΠΎΠ½Π΅Ρ‡Π½Ρ‹ΠΌ ΡƒΠ·Π»ΠΎΠΌ, ΡΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΡŽ состояния этого соСдинСния, ΡƒΠΊΠ°Π·Π°Π½ΠΈΡŽ Π½ΠΎΠΌΠ΅Ρ€Π° ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹Ρ… Π±Π°ΠΉΡ‚ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ΅ ΠΏΠ°ΠΊΠ΅Ρ‚Π°, ΠΈ увСдомлСниях ΠΎ получСниях с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Π½ΠΎΠΌΠ΅Ρ€Π° подтвСрТдСния Β«acknowledge numberΒ».

Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ, для ΠΏΠΎΠ²Ρ‹ΡˆΠ΅Π½ΠΈΡ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ (Ρ‚.Π΅. ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ сСгмСнта Π±Π΅Π· получСния подтвСрТдСния) TCP ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ‚Π°ΠΊ Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ ΠΎΠΊΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ β€” число Π±Π°ΠΉΡ‚ Π΄Π°Π½Π½Ρ‹Ρ… ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ сСгмСнта ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ ΠΏΡ€ΠΈΠ½ΡΡ‚ΡŒ.

Π‘ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ с TCP ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΎΠΌ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡ‚ΡŒΡΡ Π² rfc 793, с UDP Π² rfc 768, Π³Π΄Π΅ ΠΎΠ½ΠΈ, собствСнно говоря, ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹.

Из Π²Ρ‹ΡˆΠ΅ΠΎΠΏΠΈΡΠ°Π½Π½ΠΎΠ³ΠΎ, понятно, Ρ‡Ρ‚ΠΎ для создания Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠ³ΠΎ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° доставки сообщСний ΠΏΠΎΠ²Π΅Ρ€Ρ… UDP (Π² дальнСйшСм Π±ΡƒΠ΄Π΅ΠΌ Π½Π°Π·Ρ‹Π²Π°Ρ‚ΡŒ Reliable UDP), трСбуСтся Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ схоТиС с TCP ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ…. А ΠΈΠΌΠ΅Π½Π½ΠΎ:

  • ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ состояниС соСдинСния
  • ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π½ΡƒΠΌΠ΅Ρ€Π°Ρ†ΠΈΡŽ сСгмСнтов
  • ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Ρ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ подтвСрТдСния
  • ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡƒΠΏΡ€ΠΎΡ‰Π΅Π½Π½Ρ‹ΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ ΠΎΠΊΠ½Π°, для увСличСния пропускной способности ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°

Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ, трСбуСтся:

  • ΡΠΈΠ³Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎ Π½Π°Ρ‡Π°Π»Π΅ сообщСния, для выдСлСния рСсурсов ΠΏΠΎΠ΄ соСдинСниС
  • ΡΠΈΠ³Π½Π°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ± ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠΈ сообщСния, для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ³ΠΎ сообщСния Π²Ρ‹ΡˆΠ΅ΡΡ‚ΠΎΡΡ‰Π΅ΠΌΡƒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ ΠΈ высвобоТдСния рСсурсов ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°
  • ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Ρƒ для ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹Ρ… соСдинСний ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠΉ доставки, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ «чистый» UDP

Π—Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Reliable UDP

Вспомним, Ρ‡Ρ‚ΠΎ UDP Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΠ° инкапсулируСтся Π² IP Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡƒ. ΠŸΠ°ΠΊΠ΅Ρ‚ Reliable UDP соотвСтствСнно «заворачиваСтся» Π² UDP Π΄Π΅ΠΉΡ‚Π°Π³Ρ€Π°ΠΌΠΌΡƒ.
Π˜Π½ΠΊΠ°ΠΏΡΡƒΠ»ΡΡ†ΠΈΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° Reliable UDP:РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° Reliable UDP достаточно простая:

РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

  • Flags – ΡƒΠΏΡ€Π°Π²Π»ΡΡŽΡ‰ΠΈΠ΅ Ρ„Π»Π°Π³ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚Π°
  • MessageType – Ρ‚ΠΈΠΏ сообщСния, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π²Ρ‹ΡˆΠ΅ΡΡ‚ΠΎΡΡ‰ΠΈΠΌΠΈ прилоТСниями, для подписки Π½Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Π΅ сообщСния
  • TransmissionId β€” Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ, вмСстС с адрСсом ΠΈ ΠΏΠΎΡ€Ρ‚ΠΎΠΌ получатСля ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎ опрСдСляСт соСдинСниС
  • PacketNumber – Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠ°ΠΊΠ΅Ρ‚Π°
  • Options – Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΎΠΏΡ†ΠΈΠΈ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°. Π’ случаС ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для указания Ρ€Π°Π·ΠΌΠ΅Ρ€Π° сообщСния

Π€Π»Π°Π³ΠΈ Π±Ρ‹Π²Π°ΡŽΡ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅:

  • FirstPacket β€” ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ сообщСния
  • NoAsk β€” сообщСниС Π½Π΅ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° подтвСрТдСния
  • LastPacket β€” послСдний ΠΏΠ°ΠΊΠ΅Ρ‚ сообщСния
  • RequestForPacket β€” ΠΏΠ°ΠΊΠ΅Ρ‚ подтвСрТдСния ΠΈΠ»ΠΈ запрос Π½Π° потСрянный ΠΏΠ°ΠΊΠ΅Ρ‚

ΠžΠ±Ρ‰ΠΈΠ΅ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°

Π’Π°ΠΊ ΠΊΠ°ΠΊ Reliable UDP ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ Π½Π° Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Ρƒ сообщСния ΠΌΠ΅ΠΆΠ΄Ρƒ двумя ΡƒΠ·Π»Π°ΠΌΠΈ, ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡƒΠΌΠ΅Ρ‚ΡŒ ΡƒΡΡ‚Π°Π½Π°Π²Π»ΠΈΠ²Π°Ρ‚ΡŒ соСдинСниС с Π΄Ρ€ΡƒΠ³ΠΎΠΉ стороной. Для установки соСдинСния сторона-ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ посылаСт ΠΏΠ°ΠΊΠ΅Ρ‚ с Ρ„Π»Π°Π³ΠΎΠΌ FirstPacket, ΠΎΡ‚Π²Π΅Ρ‚ Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ·Π½Π°Ρ‡Π°Ρ‚ΡŒ установку соСдинСния. ВсС ΠΎΡ‚Π²Π΅Ρ‚Π½Ρ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, ΠΈΠ»ΠΈ, ΠΏΠΎ-Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ, ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ подтвСрТдСния, всСгда Π²Ρ‹ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ поля PacketNumber Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡ†Ρƒ большС, Ρ‡Π΅ΠΌ самоС большоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ PacketNumber Ρƒ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ ΠΏΡ€ΠΈΡˆΠ΅Π΄ΡˆΠΈΡ… ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². Π’ ΠΏΠΎΠ»Π΅ Options для ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° записываСтся Ρ€Π°Π·ΠΌΠ΅Ρ€ сообщСния.

Для Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ соСдинСния ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΏΠΎΡ…ΠΎΠΆΠΈΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ. Π’ послСднСм ΠΏΠ°ΠΊΠ΅Ρ‚Π΅ сообщСния устанавливаСтся Ρ„Π»Π°Π³ LastPacket. Π’ ΠΎΡ‚Π²Π΅Ρ‚Π½ΠΎΠΌ ΠΏΠ°ΠΊΠ΅Ρ‚Π΅ указываСтся Π½ΠΎΠΌΠ΅Ρ€ послСднСго ΠΏΠ°ΠΊΠ΅Ρ‚Π° + 1, Ρ‡Ρ‚ΠΎ для ΠΏΡ€ΠΈΡ‘ΠΌΠ½ΠΎΠΉ стороны ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ ΡƒΡΠΏΠ΅ΡˆΠ½ΡƒΡŽ доставку сообщСния.
Π”ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ° установлСниС ΠΈ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΠ΅ соСдинСния:РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Когда соСдинСниС установлСно, начинаСтся ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Π΄Π°Π½Π½Ρ‹Ρ…. Π”Π°Π½Π½Ρ‹Π΅ ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‚ΡΡ Π±Π»ΠΎΠΊΠ°ΠΌΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Π±Π»ΠΎΠΊ, ΠΊΡ€ΠΎΠΌΠ΅ послСднСго, содСрТит фиксированноС количСство ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². Оно Ρ€Π°Π²Π½ΠΎ Ρ€Π°Π·ΠΌΠ΅Ρ€Ρƒ ΠΎΠΊΠ½Π° ΠΏΡ€ΠΈΠ΅ΠΌΠ°/ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ. ПослСдний Π±Π»ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ мСньшСС количСство ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². ПослС ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ°, сторона-ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ подтвСрТдСния ΠΎ доставкС, Π»ΠΈΠ±ΠΎ запроса Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку потСрянных ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², оставляя ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ ΠΎΠΊΠ½ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ°/ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ для получСния ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠ². ПослС получСния подтвСрТдСния ΠΎ доставкС Π±Π»ΠΎΠΊΠ°, ΠΎΠΊΠ½ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌ/ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ сдвигаСтся ΠΈ отправляСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Π±Π»ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ….

Π‘Ρ‚ΠΎΡ€ΠΎΠ½Π°-ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚Π΅Π»ΡŒ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ провСряСтся Π½Π° ΠΏΠΎΠΏΠ°Π΄Π°Π½ΠΈΠ΅ Π² ΠΎΠΊΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ. НС ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠ΅ Π² ΠΎΠΊΠ½ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΈ Π΄ΡƒΠ±Π»ΠΈΠΊΠ°Ρ‚Ρ‹ ΠΎΡ‚ΡΠ΅ΠΈΠ²Π°ΡŽΡ‚ΡΡ. Π’.ΠΊ. Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΎΠΊΠ½Π° сторого фиксирован ΠΈ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ² Ρƒ получатСля ΠΈ Ρƒ отправитСля, Ρ‚ΠΎ Π² случаС доставки Π±Π»ΠΎΠΊΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π±Π΅Π· ΠΏΠΎΡ‚Π΅Ρ€ΡŒ, ΠΎΠΊΠ½ΠΎ сдвигаСтся для ΠΏΡ€ΠΈΠ΅ΠΌΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π³ΠΎ Π±Π»ΠΎΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ отправляСтся ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎ доставкС. Если ΠΎΠΊΠ½ΠΎ Π½Π΅ заполнится Π·Π° установлСнный Ρ€Π°Π±ΠΎΡ‡ΠΈΠΌ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ΠΎΠΌ ΠΏΠ΅Ρ€ΠΈΠΎΠ΄, Ρ‚ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΏΡƒΡ‰Π΅Π½Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° Ρ‚ΠΎ, ΠΊΠ°ΠΊΠΈΠ΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ Π½Π΅ Π±Ρ‹Π»ΠΈ доставлСны ΠΈ Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Ρ‹ запросы Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку.
Π”ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠΉ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ:РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Π’Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρ‹ ΠΈ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Ρ‹ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°

БущСствуСт нСсколько ΠΏΡ€ΠΈΡ‡ΠΈΠ½, ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ установлСно соСдинСниС. НапримСр, Ссли ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰Π°Ρ сторона Π²Π½Π΅ сСти. Π’ Ρ‚Π°ΠΊΠΎΠΌ случаС, ΠΏΡ€ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ соСдинСниС, соСдинСниС Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΊΡ€Ρ‹Ρ‚ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρƒ. Π’ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Reliable UDP ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π΄Π²Π° Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° для установки Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚ΠΎΠ². ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ, Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ Ρ‚Π°ΠΉΠΌΠ΅Ρ€, слуТит для оТидания ΠΎΡ‚Π²Π΅Ρ‚Π° ΠΎΡ‚ ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎΠ³ΠΎ хоста. Если ΠΎΠ½ срабатываСт Π½Π° сторонС-ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»Π΅, Ρ‚ΠΎ выполняСтся повторная ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° послСднСго ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π°. Если ΠΆΠ΅ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ срабатываСт Ρƒ получатСля, Ρ‚ΠΎ выполняСтся ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° потСрянныС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ΡΡ запросы Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку.

Π’Ρ‚ΠΎΡ€ΠΎΠΉ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ – Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ для закрытия соСдинСния Π² случаС отсутствия связи ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ. Для стороны-отправитСля ΠΎΠ½ запускаСтся сразу послС срабатывания Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π°, ΠΈ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ ΠΎΡ‚Π²Π΅Ρ‚Π° ΠΎΡ‚ ΡƒΠ΄Π°Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΡƒΠ·Π»Π°. Π’ случаС отсутствия ΠΎΡ‚Π²Π΅Ρ‚Π° Π·Π° установлСнный ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ – соСдинСниС Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ ΠΈ рСсурсы ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°ΡŽΡ‚ΡΡ. Для стороны-получатСля, Ρ‚Π°ΠΉΠΌΠ΅Ρ€ закрытия соСдинСния запускаСтся послС Π΄Π²ΠΎΠΉΠ½ΠΎΠ³ΠΎ срабатывания Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π°. Π­Ρ‚ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ для страховки ΠΎΡ‚ ΠΏΠΎΡ‚Π΅Ρ€ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚Π° подтвСрТдСния. ΠŸΡ€ΠΈ срабатывании Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π°, Ρ‚Π°ΠΊΠΆΠ΅ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ соСдинСниС ΠΈ Π²Ρ‹ΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°ΡŽΡ‚ΡΡ рСсурсы.

Π”ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ° состояний ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Reliable UDP

ΠŸΡ€ΠΈΠ½Ρ†ΠΈΠΏΡ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ‹ Π² ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠΌ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚Π΅, ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ состояниС ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΡƒΡŽ Π»ΠΎΠ³ΠΈΠΊΡƒ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ².
Π”ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ° состояний Reliable UDP:

РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Closed – Π² Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Π½Π΅ являСтся состояниСм, это стартовая ΠΈ конСчная Ρ‚ΠΎΡ‡ΠΊΠ° для Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚Π°. Π—Π° состояниС Closed принимаСтся Π±Π»ΠΎΠΊ управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ, рСализуя асинхронный UDP сСрвСр, пСрСнаправляСт ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ Π² ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ соСдинСния ΠΈ запускаСт ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ состояний.

FirstPacketSending – Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ состояниС, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ находится исходящСС соСдинСниС ΠΏΡ€ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ΅ сообщСния.

Π’ этом состоянии отправляСтся ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ для ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Ρ… сообщСний. Для сообщСний Π±Π΅Π· подтвСрТдСния ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ, это СдинствСнноС состояниС – Π² Π½Π΅ΠΌ происходит ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° всСго сообщСния.

SendingCycle – основноС состояния для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² сообщСния.

ΠŸΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Π² Π½Π΅Π³ΠΎ ΠΈΠ· состояния FirstPacketSending осущСствляСтся послС ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° сообщСния. ИмСнно Π² это состояниС приходят всС подтвСрТдСния ΠΈ запросы Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½Ρ‹Π΅ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ. Π’Ρ‹Ρ…ΠΎΠ΄ ΠΈΠ· Π½Π΅Π³ΠΎ Π²ΠΎΠ·ΠΌΠΎΠΆΠ΅Π½ Π² Π΄Π²ΡƒΡ… случаях – Π² случаС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΉ доставки сообщСния ΠΈΠ»ΠΈ ΠΏΠΎ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρƒ.

FirstPacketReceived – Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ состояниС для получатСля сообщСния.

Π’ Π½Π΅ΠΌ провСряСтся ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΡΡ‚ΡŒ Π½Π°Ρ‡Π°Π»Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ, ΡΠΎΠ·Π΄Π°ΡŽΡ‚ΡΡ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ структуры, ΠΈ отправляСтся ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ΅ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π°.

Для сообщСния, состоящСго ΠΈΠ· СдинствСнного ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½ΠΎΠ³ΠΎ Π±Π΅Π· использования подтвСрТдСния доставки – это СдинствСнноС состояниС. ПослС ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Ρ‚Π°ΠΊΠΎΠ³ΠΎ сообщСния соСдинСниС закрываСтся.

Assembling – основноС состояниС для ΠΏΡ€ΠΈΠ΅ΠΌΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² сообщСния.

Π’ Π½Π΅ΠΌ производится запись ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π²ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° отсутствиС ΠΏΠΎΡ‚Π΅Ρ€ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠΉ ΠΎ доставкС Π±Π»ΠΎΠΊΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΈ сообщСния Ρ†Π΅Π»ΠΈΠΊΠΎΠΌ, ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° запросов Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку потСрянных ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². Π’ случаС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ³ΠΎ получСния всСго сообщСния – соСдинСниС ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ Π² состояниС Completed, ΠΈΠ½Π°Ρ‡Π΅ выполняСтся Π²Ρ‹Ρ…ΠΎΠ΄ ΠΏΠΎ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρƒ.

Completed – Π·Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ соСдинСния Π² случаС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠ³ΠΎ получСния всСго сообщСния.

Π”Π°Π½Π½ΠΎΠ΅ состояниС Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ для сборки сообщСния ΠΈ для случая, ΠΊΠΎΠ³Π΄Π° ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎ доставкС сообщСния Π±Ρ‹Π»ΠΎ потСряно ΠΏΠΎ ΠΏΡƒΡ‚ΠΈ ΠΊ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŽ. Π’Ρ‹Ρ…ΠΎΠ΄ ΠΈΠ· этого состояния производится ΠΏΠΎ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρƒ, Π½ΠΎ соСдинСниС считаСтся ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ Π·Π°ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ.

Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. Π‘Π»ΠΎΠΊ управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ

Один ΠΈΠ· ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹Ρ… элСмСнтов Reliable UDP – Π±Π»ΠΎΠΊ управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ. Π—Π°Π΄Π°Ρ‡Π° Π΄Π°Π½Π½ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ° – Ρ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΡ… соСдинСний ΠΈ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… элСмСнтов, распрСдСлСниС ΠΏΡ€ΠΈΡˆΠ΅Π΄ΡˆΠΈΡ… ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΏΠΎ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌ соСдинСниям, прСдоставлСниС интСрфСйса для ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² соСдинСнию ΠΈ рСализация API ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°. Π‘Π»ΠΎΠΊ управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΎΡ‚ UDP уровня ΠΈ пСрСнаправляСт ΠΈΡ… Π½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ Π² ΠΊΠΎΠ½Π΅Ρ‡Π½Ρ‹ΠΉ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚. Для ΠΏΡ€ΠΈΠ΅ΠΌΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π² Π½Π΅ΠΌ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½ асинхронный UDP сСрвСр.
НСкоторыС Ρ‡Π»Π΅Π½Ρ‹ класса ReliableUdpConnectionControlBlock:

internal class ReliableUdpConnectionControlBlock : IDisposable
{
  // массив Π±Π°ΠΉΡ‚ для ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π°. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для сборки входящих сообщСний    
  public ConcurrentDictionary<Tuple<EndPoint, Int32>, byte[]> IncomingStreams { get; private set;}
  // массив Π±Π°ΠΉΡ‚ для ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π°. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ исходящих сообщСний.
  public ConcurrentDictionary<Tuple<EndPoint, Int32>, byte[]> OutcomingStreams { get; private set; }
  // connection record для ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ ΠΊΠ»ΡŽΡ‡Π°.
  private readonly ConcurrentDictionary<Tuple<EndPoint, Int32>, ReliableUdpConnectionRecord> m_listOfHandlers;
  // список подписчиков Π½Π° сообщСния.
  private readonly List<ReliableUdpSubscribeObject> m_subscribers;    
  // Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ сокСт    
  private Socket m_socketIn;
  // ΠΏΠΎΡ€Ρ‚ для входящих сообщСний
  private int m_port;
  // Π»ΠΎΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ IP адрСс
  private IPAddress m_ipAddress;    
  // локальная конСчная Ρ‚ΠΎΡ‡ΠΊΠ°    
  public IPEndPoint LocalEndpoint { get; private set; }    
  // коллСкция ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ…
  // состояний ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠ³ΠΎ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚Π°
  public StatesCollection States { get; private set; }
  // Π³Π΅Π½Π΅Ρ€Π°Ρ‚ΠΎΡ€ случайных чисСл. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для создания TransmissionId
  private readonly RNGCryptoServiceProvider m_randomCrypto;    	
  //...
}

РСализация асинхронного UDP сСрвСра:

private void Receive()
{
  EndPoint connectedClient = new IPEndPoint(IPAddress.Any, 0);
  // создаСм Π½ΠΎΠ²Ρ‹ΠΉ Π±ΡƒΡ„Π΅Ρ€, для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ socket.BeginReceiveFrom 
  byte[] buffer = new byte[DefaultMaxPacketSize + ReliableUdpHeader.Length];
  // ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅ΠΌ Π±ΡƒΡ„Π΅Ρ€ Π² качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° для асинхронного ΠΌΠ΅Ρ‚ΠΎΠ΄Π°
  this.m_socketIn.BeginReceiveFrom(buffer, 0, buffer.Length, SocketFlags.None, ref connectedClient, EndReceive, buffer);
}   

private void EndReceive(IAsyncResult ar)
{
  EndPoint connectedClient = new IPEndPoint(IPAddress.Any, 0);
  int bytesRead = this.m_socketIn.EndReceiveFrom(ar, ref connectedClient);
  //ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½, Π³ΠΎΡ‚ΠΎΠ²Ρ‹ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ        
  Receive();
  // Ρ‚.ΠΊ. ΠΏΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠΈΠΉ способ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ вопрос с Π±ΡƒΡ„Π΅Ρ€ΠΎΠΌ - ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ссылку Π½Π° Π½Π΅Π³ΠΎ 
  // ΠΈΠ· IAsyncResult.AsyncState        
  byte[] bytes = ((byte[]) ar.AsyncState).Slice(0, bytesRead);
  // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚Π°        
  ReliableUdpHeader header;
  if (!ReliableUdpStateTools.ReadReliableUdpHeader(bytes, out header))
  {          
    // ΠΏΡ€ΠΈΡˆΠ΅Π» Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ - отбрасываСм Π΅Π³ΠΎ
    return;
  }
  // конструируСм ΠΊΠ»ΡŽΡ‡ для опрСдСлСния connection record’а для ΠΏΠ°ΠΊΠ΅Ρ‚Π°
  Tuple<EndPoint, Int32> key = new Tuple<EndPoint, Int32>(connectedClient, header.TransmissionId);
  // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ connection record ΠΈΠ»ΠΈ создаСм Π½ΠΎΠ²ΡƒΡŽ
  ReliableUdpConnectionRecord record = m_listOfHandlers.GetOrAdd(key, new ReliableUdpConnectionRecord(key, this, header.ReliableUdpMessageType));
  // запускаСм ΠΏΠ°ΠΊΠ΅Ρ‚ Π² ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ Π² ΠΊΠΎΠ½Π΅Ρ‡Π½Ρ‹ΠΉ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚
  record.State.ReceivePacket(record, header, bytes);
}

Для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ сообщСния создаСтся структура, содСрТащая свСдСния ΠΎ соСдинСнии. Вакая структура называСтся connection record.
НСкоторыС Ρ‡Π»Π΅Π½Ρ‹ класса ReliableUdpConnectionRecord:

internal class ReliableUdpConnectionRecord : IDisposable
{    
  // массив Π±Π°ΠΉΡ‚ с сообщСниСм    
  public byte[] IncomingStream { get; set; }
  // ссылка Π½Π° состояниС ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠ³ΠΎ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚Π°    
  public ReliableUdpState State { get; set; }    
  // ΠΏΠ°Ρ€Π°, ΠΎΠ΄Π½ΠΎΠ·Π½Π°Ρ‡Π½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰Π°Ρ connection record
  // Π² Π±Π»ΠΎΠΊΠ΅ управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ     
  public Tuple<EndPoint, Int32> Key { get; private set;}
  // ниТняя Π³Ρ€Π°Π½ΠΈΡ†Π° ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΠΊΠ½Π°    
  public int WindowLowerBound;
  // Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΎΠΊΠ½Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ
  public readonly int WindowSize;     
  // Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠ°ΠΊΠ΅Ρ‚Π° для ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ
  public int SndNext;
  // количСство ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² для ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ
  public int NumberOfPackets;
  // Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ (ΠΈΠΌΠ΅Π½Π½ΠΎ ΠΎΠ½ ΠΈ Π΅ΡΡ‚ΡŒ вторая Ρ‡Π°ΡΡ‚ΡŒ Tuple)
  // для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ сообщСния свой	
  public readonly Int32 TransmissionId;
  // ΡƒΠ΄Π°Π»Π΅Π½Π½Ρ‹ΠΉ IP endpoint – собствСнно ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚Π΅Π»ΡŒ сообщСния
  public readonly IPEndPoint RemoteClient;
  // Ρ€Π°Π·ΠΌΠ΅Ρ€ ΠΏΠ°ΠΊΠ΅Ρ‚Π°, Π²ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°Π½ΠΈΠ΅ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ Π½Π° IP ΡƒΡ€ΠΎΠ²Π½Π΅
  // Π½Π΅ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ°Ρ‚ΡŒ MTU – (IP.Header + UDP.Header + RelaibleUDP.Header)
  public readonly int BufferSize;
  // Π±Π»ΠΎΠΊ управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ
  public readonly ReliableUdpConnectionControlBlock Tcb;
  // инкапсулируСт Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ асинхронной ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ для BeginSendMessage/EndSendMessage
  public readonly AsyncResultSendMessage AsyncResult;
  // Π½Π΅ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ подтвСрТдСния
  public bool IsNoAnswerNeeded;
  // послСдний ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ (всСгда устанавливаСтся Π² наибольший Π½ΠΎΠΌΠ΅Ρ€)
  public int RcvCurrent;
  // массив с Π½ΠΎΠΌΠ΅Ρ€Π°ΠΌΠΈ потСрянных ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²
  public int[] LostPackets { get; private set; }
  // ΠΏΡ€ΠΈΡˆΠ΅Π» Π»ΠΈ послСдний ΠΏΠ°ΠΊΠ΅Ρ‚. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΊΠ°ΠΊ bool.
  public int IsLastPacketReceived = 0;
  //...
}

Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. Бостояния

Бостояния Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‚ ΠΊΠΎΠ½Π΅Ρ‡Π½Ρ‹ΠΉ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° Reliable UDP, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ происходит основная ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². Абстрактный класс ReliableUdpState прСдоставляСт интСрфСйс для состояния:

РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Π’ΡΡŽ Π»ΠΎΠ³ΠΈΠΊΡƒ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‚ прСдставлСнныС Π²Ρ‹ΡˆΠ΅ классы, совмСстно со Π²ΡΠΏΠΎΠΌΠΎΠ³Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ классом, ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠΌ статичСскиС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, построСния Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° ReliableUdp ΠΈΠ· connection record.

Π”Π°Π»Π΅Π΅ Π±ΡƒΠ΄ΡƒΡ‚ рассмотрСны Π² подробностях Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² интСрфСйса, ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰ΠΈΡ… основныС Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΡ‹ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°.

ΠœΠ΅Ρ‚ΠΎΠ΄ DisposeByTimeout

ΠœΠ΅Ρ‚ΠΎΠ΄ DisposeByTimeout ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° высвобоТдСниС рСсурсов соСдинСния ΠΏΠΎ ΠΈΡΡ‚Π΅Ρ‡Π΅Π½ΠΈΡŽ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Π° ΠΈ для сигнализации ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΉ/Π½Π΅ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΉ доставки сообщСния.
ReliableUdpState.DisposeByTimeout:

protected virtual void DisposeByTimeout(object record)
{
  ReliableUdpConnectionRecord connectionRecord = (ReliableUdpConnectionRecord) record;      
  if (record.AsyncResult != null)
  {
    connectionRecord.AsyncResult.SetAsCompleted(false);
  }
  connectionRecord.Dispose();
}

Он ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² состоянии Completed.
Completed.DisposeByTimeout:

protected override void DisposeByTimeout(object record)
{
  ReliableUdpConnectionRecord connectionRecord = (ReliableUdpConnectionRecord) record;
  // сообщаСм ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΌ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ сообщСния
  SetAsCompleted(connectionRecord);        
}

ΠœΠ΅Ρ‚ΠΎΠ΄ ProcessPackets

ΠœΠ΅Ρ‚ΠΎΠ΄ ProcessPackets ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈΠ»ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². ВызываСтся Π½Π°ΠΏΡ€ΡΠΌΡƒΡŽ, Π»ΠΈΠ±ΠΎ Ρ‡Π΅Ρ€Π΅Π· Ρ‚Π°ΠΉΠΌΠ΅Ρ€ оТидания ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ².

Π’ состоянии Assembling ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ ΠΈ ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ потСрянных ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΈ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Π² состояниС Completed, Π² случаС получСния послСднСго ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ прохоТдСния ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΉ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠΈ
Assembling.ProcessPackets:

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  if (connectionRecord.IsDone != 0)
    return;
  if (!ReliableUdpStateTools.CheckForNoPacketLoss(connectionRecord, connectionRecord.IsLastPacketReceived != 0))
  {
    // Π΅ΡΡ‚ΡŒ потСрянныС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, отсылаСм запросы Π½Π° Π½ΠΈΡ…
    foreach (int seqNum in connectionRecord.LostPackets)
    {
      if (seqNum != 0)
      {
        ReliableUdpStateTools.SendAskForLostPacket(connectionRecord, seqNum);
      }
    }
    // устанавливаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ Ρ€Π°Π·, для ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠΉ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ
    if (!connectionRecord.TimerSecondTry)
    {
      connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
      connectionRecord.TimerSecondTry = true;
      return;
    }
    // Ссли послС Π΄Π²ΡƒΡ… ΠΏΠΎΠΏΡ‹Ρ‚ΠΎΠΊ срабатываний WaitForPacketTimer 
    // Π½Π΅ ΡƒΠ΄Π°Π»ΠΎΡΡŒ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ - запускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ соСдинСния
    StartCloseWaitTimer(connectionRecord);
  }
  else if (connectionRecord.IsLastPacketReceived != 0)
  // ΡƒΡΠΏΠ΅ΡˆΠ½Π°Ρ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° 
  {
    // высылаСм ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ Π±Π»ΠΎΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ…
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
    connectionRecord.State = connectionRecord.Tcb.States.Completed;
    connectionRecord.State.ProcessPackets(connectionRecord);
    // вмСсто ΠΌΠΎΠΌΠ΅Π½Ρ‚Π°Π»ΡŒΠ½ΠΎΠΉ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ рСсурсов
    // запускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€, Π½Π° случай, Ссли
    // Ссли послСдний ack Π½Π΅ Π΄ΠΎΠΉΠ΄Π΅Ρ‚ Π΄ΠΎ отправитСля ΠΈ ΠΎΠ½ запросит Π΅Π³ΠΎ снова.
    // ΠΏΠΎ ΡΡ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π½ΠΈΡŽ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° - Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ рСсурсы
    // Π² состоянии Completed ΠΌΠ΅Ρ‚ΠΎΠ΄ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½
    StartCloseWaitTimer(connectionRecord);
  }
  // это случай, ΠΊΠΎΠ³Π΄Π° ack Π½Π° Π±Π»ΠΎΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π±Ρ‹Π» потСрян
  else
  {
    if (!connectionRecord.TimerSecondTry)
    {
      ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
      connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
      connectionRecord.TimerSecondTry = true;
      return;
    }
    // запускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ соСдинСния
    StartCloseWaitTimer(connectionRecord);
  }
}

Π’ состоянии SendingCycle этот ΠΌΠ΅Ρ‚ΠΎΠ΄ вызываСтся Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Ρƒ, ΠΈ ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΡƒ послСднСго сообщСния, Π° Ρ‚Π°ΠΊΠΆΠ΅ Π·Π° Π²ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° закрытия соСдинСния.
SendingCycle.ProcessPackets:

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  if (connectionRecord.IsDone != 0)
    return;        
  // отправляСм ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ послСдний ΠΏΠ°ΠΊΠ΅Ρ‚ 
  // ( Π² случаС восстановлСния соСдинСния ΡƒΠ·Π΅Π»-ΠΏΡ€ΠΈΠ΅ΠΌΠ½ΠΈΠΊ Π·Π°Π½ΠΎΠ²ΠΎ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ запросы, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎ Π½Π΅Π³ΠΎ Π½Π΅ дошли)        
  ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord, connectionRecord.SndNext - 1));
  // Π²ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ CloseWait – для оТидания восстановлСния соСдинСния ΠΈΠ»ΠΈ Π΅Π³ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ
  StartCloseWaitTimer(connectionRecord);
}

Π’ состоянии Completed ΠΌΠ΅Ρ‚ΠΎΠ΄ останавливаСт Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅Ρ‚ сообщСниС подписчикам.
Completed.ProcessPackets:

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  if (connectionRecord.WaitForPacketsTimer != null)
    connectionRecord.WaitForPacketsTimer.Dispose();
  // собираСм сообщСниС ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅ΠΌ Π΅Π³ΠΎ подписчикам
  ReliableUdpStateTools.CreateMessageFromMemoryStream(connectionRecord);
}

ΠœΠ΅Ρ‚ΠΎΠ΄ ReceivePacket

Π’ состоянии FirstPacketReceived основная Π·Π°Π΄Π°Ρ‡Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° β€” ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π»ΠΈ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ сообщСния ΠΏΡ€ΠΈΡˆΠ΅Π» Π½Π° интСрфСйс, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΡΠΎΠ±Ρ€Π°Ρ‚ΡŒ сообщСниС состоящСС ΠΈΠ· СдинствСнного ΠΏΠ°ΠΊΠ΅Ρ‚Π°.
FirstPacketReceived.ReceivePacket:

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket))
    // отбрасываСм ΠΏΠ°ΠΊΠ΅Ρ‚
    return;
  // комбинация Π΄Π²ΡƒΡ… Ρ„Π»Π°Π³ΠΎΠ² - FirstPacket ΠΈ LastPacket - Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ Ρ‡Ρ‚ΠΎ Ρƒ нас СдинствСнноС сообщСниС
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket) &
      header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
  {
    ReliableUdpStateTools.CreateMessageFromSinglePacket(connectionRecord, header, payload.Slice(ReliableUdpHeader.Length, payload.Length));
    if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.NoAsk))
    {
      // отправляСм ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅          
      ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
    }
    SetAsCompleted(connectionRecord);
    return;
  }
  // by design всС packet numbers Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‚ΡΡ с 0;
  if (header.PacketNumber != 0)          
    return;
  ReliableUdpStateTools.InitIncomingBytesStorage(connectionRecord, header);
  ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
  // считаСм ΠΊΠΎΠ»-Π²ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΡ€ΠΈΠΉΡ‚ΠΈ
  connectionRecord.NumberOfPackets = (int)Math.Ceiling((double) ((double) connectionRecord.IncomingStream.Length/(double) connectionRecord.BufferSize));
  // записываСм Π½ΠΎΠΌΠ΅Ρ€ послСднСго ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° (0)
  connectionRecord.RcvCurrent = header.PacketNumber;
  // послС сдвинули ΠΎΠΊΠ½ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π½Π° 1
  connectionRecord.WindowLowerBound++;
  // ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ состояниС
  connectionRecord.State = connectionRecord.Tcb.States.Assembling;
  // Ссли Π½Π΅ трСбуСтся ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅
  // запускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ высвободит всС структуры         
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.NoAsk))
  {
    connectionRecord.CloseWaitTimer = new Timer(DisposeByTimeout, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
  }
  else
  {
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
    connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
  }
}

Π’ состоянии SendingCycle этот ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ для ΠΏΡ€ΠΈΠ΅ΠΌΠ° ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠΉ ΠΎ доставкС ΠΈ запросов ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠΉ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ.
SendingCycle.ReceivePacket:

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  if (connectionRecord.IsDone != 0)
    return;
  if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.RequestForPacket))
    return;
  // расчСт ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠΉ Π³Ρ€Π°Π½ΠΈΡ†Ρ‹ ΠΎΠΊΠ½Π°
  // бСрСтся Π³Ρ€Π°Π½ΠΈΡ†Π° ΠΎΠΊΠ½Π° + 1, для получСния ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠΉ доставки
  int windowHighestBound = Math.Min((connectionRecord.WindowLowerBound + connectionRecord.WindowSize), (connectionRecord.NumberOfPackets));
  // ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° ΠΏΠΎΠΏΠ°Π΄Π°Π½ΠΈΠ΅ Π² ΠΎΠΊΠ½ΠΎ        
  if (header.PacketNumber < connectionRecord.WindowLowerBound || header.PacketNumber > windowHighestBound)
    return;
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚ΡŒ Π½Π° послСдний ΠΏΠ°ΠΊΠ΅Ρ‚:
  if (header.PacketNumber == connectionRecord.NumberOfPackets)
  {
    // ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½Π°
    Interlocked.Increment(ref connectionRecord.IsDone);
    SetAsCompleted(connectionRecord);
    return;
  }
  // это ΠΎΡ‚Π²Π΅Ρ‚ Π½Π° ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ c ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ΠΌ         
  if ((header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket) && header.PacketNumber == 1))
  {
    // бСз сдвига окна
    SendPacket(connectionRecord);
  }
  // ΠΏΡ€ΠΈΡˆΠ»ΠΎ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ Π±Π»ΠΎΠΊΠ° Π΄Π°Π½Π½Ρ‹Ρ…
  else if (header.PacketNumber == windowHighestBound)
  {
    // сдвигаСм ΠΎΠΊΠ½ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌ/ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ
    connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
    // обнуляСм массив контроля ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ
    connectionRecord.WindowControlArray.Nullify();
    // отправляСм Π±Π»ΠΎΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²
    SendPacket(connectionRecord);
  }
  // это запрос Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Ρƒ – отправляСм Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚          
  else
    ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord, header.PacketNumber));
}

Π’ состоянии Assembling Π² ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ ReceivePacket происходит основная Ρ€Π°Π±ΠΎΡ‚Π° ΠΏΠΎ сборкС сообщСния ΠΈΠ· ΠΏΠΎΡΡ‚ΡƒΠΏΠ°ΡŽΡ‰ΠΈΡ… ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ².
Assembling.ReceivePacket:

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  if (connectionRecord.IsDone != 0)
    return;
  // ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² с ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹ΠΌ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΎΠΌ подтвСрТдСния доставки
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.NoAsk))
  {
    // сбрасываСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€
    connectionRecord.CloseWaitTimer.Change(connectionRecord.LongTimerPeriod, -1);
    // записываСм Π΄Π°Π½Π½Ρ‹Π΅
    ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
    // Ссли ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ с послСдним Ρ„Π»Π°Π³ΠΎΠΌ - Π΄Π΅Π»Π°Π΅ΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅ΠΌ          
    if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
    {
      connectionRecord.State = connectionRecord.Tcb.States.Completed;
      connectionRecord.State.ProcessPackets(connectionRecord);
    }
    return;
  }        
  // расчСт ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠΉ Π³Ρ€Π°Π½ΠΈΡ†Ρ‹ ΠΎΠΊΠ½Π°
  int windowHighestBound = Math.Min((connectionRecord.WindowLowerBound + connectionRecord.WindowSize - 1), (connectionRecord.NumberOfPackets - 1));
  // отбрасываСм Π½Π΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠ΅ Π² ΠΎΠΊΠ½ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹
  if (header.PacketNumber < connectionRecord.WindowLowerBound || header.PacketNumber > (windowHighestBound))
    return;
  // отбрасываСм Π΄ΡƒΠ±Π»ΠΈΠΊΠ°Ρ‚Ρ‹
  if (connectionRecord.WindowControlArray.Contains(header.PacketNumber))
    return;
  // записываСм Π΄Π°Π½Π½Ρ‹Π΅ 
  ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
  // ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅ΠΌ счСтчик ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²        
  connectionRecord.PacketCounter++;
  // записываСм Π² массив управлСния ΠΎΠΊΠ½ΠΎΠΌ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠ°ΠΊΠ΅Ρ‚Π°        
  connectionRecord.WindowControlArray[header.PacketNumber - connectionRecord.WindowLowerBound] = header.PacketNumber;
  // устанавливаСм наибольший ΠΏΡ€ΠΈΡˆΠ΅Π΄ΡˆΠΈΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚        
  if (header.PacketNumber > connectionRecord.RcvCurrent)
    connectionRecord.RcvCurrent = header.PacketNumber;
  // пСрСзапускам Ρ‚Π°ΠΉΠΌΠ΅Ρ€Ρ‹        
  connectionRecord.TimerSecondTry = false;
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // Ссли ΠΏΡ€ΠΈΡˆΠ΅Π» послСдний ΠΏΠ°ΠΊΠ΅Ρ‚
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
  {
    Interlocked.Increment(ref connectionRecord.IsLastPacketReceived);
  }
  // Ссли Π½Π°ΠΌ ΠΏΡ€ΠΈΡˆΠ»ΠΈ всС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΎΠΊΠ½Π°, Ρ‚ΠΎ сбрасываСм счСтчик
  // ΠΈ высылаСм ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅
  else if (connectionRecord.PacketCounter == connectionRecord.WindowSize)
  {
    // сбрасываСм счСтчик.      
    connectionRecord.PacketCounter = 0;
    // сдвинули ΠΎΠΊΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ
    connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
    // ΠΎΠ±Π½ΡƒΠ»Π΅Π½ΠΈΠ΅ массива управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ
    connectionRecord.WindowControlArray.Nullify();
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
  }
  // Ссли послСдний ΠΏΠ°ΠΊΠ΅Ρ‚ ΡƒΠΆΠ΅ имССтся        
  if (Thread.VolatileRead(ref connectionRecord.IsLastPacketReceived) != 0)
  {
    // провСряСм ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹          
    ProcessPackets(connectionRecord);
  }
}

Π’ состоянии Completed СдинствСнная Π·Π°Π΄Π°Ρ‡Π° ΠΌΠ΅Ρ‚ΠΎΠ΄Π° β€” ΠΎΡ‚ΠΎΡΠ»Π°Ρ‚ΡŒ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠ΅ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎΠ± ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΠΉ доставкС сообщСния.
Completed.ReceivePacket:

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // повторная ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° послСднСго ΠΏΠ°ΠΊΠ΅Ρ‚Π° Π² связи с Ρ‚Π΅ΠΌ,
  // Ρ‡Ρ‚ΠΎ послСдний ack Π½Π΅ дошСл Π΄ΠΎ отправитСля
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
  {
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
  }
}

ΠœΠ΅Ρ‚ΠΎΠ΄ SendPacket

Π’ состоянии FirstPacketSending этот ΠΌΠ΅Ρ‚ΠΎΠ΄ осущСствляСт ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΡƒ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° Π΄Π°Π½Π½Ρ‹Ρ…, ΠΈΠ»ΠΈ, Ссли сообщСниС Π½Π΅ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅ доставки β€” всС сообщСниС.
FirstPacketSending.SendPacket:

public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{
  connectionRecord.PacketCounter = 0;
  connectionRecord.SndNext = 0;
  connectionRecord.WindowLowerBound = 0;       
  // Ссли подтвСрТдСния Π½Π΅ трСбуСтся - отправляСм всС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹
  // ΠΈ высвобоТдаСм рСсурсы
  if (connectionRecord.IsNoAnswerNeeded)
  {
    // Π—Π΄Π΅ΡΡŒ происходит ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° As Is
    do
    {
      ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, ReliableUdpStateTools. CreateReliableUdpHeader(connectionRecord)));
      connectionRecord.SndNext++;
    } while (connectionRecord.SndNext < connectionRecord.NumberOfPackets);
    SetAsCompleted(connectionRecord);
    return;
  }
  // создаСм Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ отправляСм Π΅Π³ΠΎ 
  ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord);
  ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header));
  // ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅ΠΌ счСтчик
  connectionRecord.SndNext++;
  // сдвигаСм окно
  connectionRecord.WindowLowerBound++;
  connectionRecord.State = connectionRecord.Tcb.States.SendingCycle;
  // ЗапускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€
  connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
}

Π’ состоянии SendingCycle Π² этом ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ происходит ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° Π±Π»ΠΎΠΊΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ².
SendingCycle.SendPacket:

public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{      
  // отправляСм Π±Π»ΠΎΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²      
  for (connectionRecord.PacketCounter = 0;
        connectionRecord.PacketCounter < connectionRecord.WindowSize &&
        connectionRecord.SndNext < connectionRecord.NumberOfPackets;
        connectionRecord.PacketCounter++)
  {
    ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord);
    ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header));
    connectionRecord.SndNext++;
  }
  // Π½Π° случай большого ΠΎΠΊΠ½Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ, пСрСзапускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€ послС ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ
  connectionRecord.WaitForPacketsTimer.Change( connectionRecord.ShortTimerPeriod, -1 );
  if ( connectionRecord.CloseWaitTimer != null )
  {
    connectionRecord.CloseWaitTimer.Change( -1, -1 );
  }
}

Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈ установлСниС соСдинСний

Π’Π΅ΠΏΠ΅Ρ€ΡŒ, ΠΊΠΎΠ³Π΄Π° ΠΌΡ‹ познакомились с основными состояниями ΠΈ ΠΌΠ΅Ρ‚ΠΎΠ΄Π°ΠΌΠΈ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΌΠΈ для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ состояний, ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ нСсколько ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°.
Π”ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… Π² Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½Ρ‹Ρ… условиях:РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Рассмотрим ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎ созданиС connection record для соСдинСния ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΡƒ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π°. Π˜Π½ΠΈΡ†ΠΈΠ°Ρ‚ΠΎΡ€ΠΎΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ всСгда выступаСт ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅Π΅ API-ΠΌΠ΅Ρ‚ΠΎΠ΄ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ сообщСния. Π”Π°Π»Π΅Π΅ задСйствуСтся ΠΌΠ΅Ρ‚ΠΎΠ΄ StartTransmission Π±Π»ΠΎΠΊΠ° управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ, Π·Π°ΠΏΡƒΡΠΊΠ°ΡŽΡ‰ΠΈΠΉ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Ρƒ Π΄Π°Π½Π½Ρ‹Ρ… для Π½ΠΎΠ²ΠΎΠ³ΠΎ сообщСния.
Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ исходящСго соСдинСния:

private void StartTransmission(ReliableUdpMessage reliableUdpMessage, EndPoint endPoint, AsyncResultSendMessage asyncResult)
{
  if (m_isListenerStarted == 0)
  {
    if (this.LocalEndpoint == null)
    {
      throw new ArgumentNullException( "", "You must use constructor with parameters or start listener before sending message" );
    }
    // запускаСм ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ входящих ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²
    StartListener(LocalEndpoint);
  }
  // создаСм ΠΊΠ»ΡŽΡ‡ для словаря, Π½Π° основС EndPoint ΠΈ ReliableUdpHeader.TransmissionId        
  byte[] transmissionId = new byte[4];
  // создаСм случайный Π½ΠΎΠΌΠ΅Ρ€ transmissionId        
  m_randomCrypto.GetBytes(transmissionId);
  Tuple<EndPoint, Int32> key = new Tuple<EndPoint, Int32>(endPoint, BitConverter.ToInt32(transmissionId, 0));
  // создаСм Π½ΠΎΠ²ΡƒΡŽ запись для соСдинСния ΠΈ провСряСм, 
  // сущСствуСт Π»ΠΈ ΡƒΠΆΠ΅ Ρ‚Π°ΠΊΠΎΠΉ Π½ΠΎΠΌΠ΅Ρ€ Π² Π½Π°ΡˆΠΈΡ… словарях
  if (!m_listOfHandlers.TryAdd(key, new ReliableUdpConnectionRecord(key, this, reliableUdpMessage, asyncResult)))
  {
    // Ссли сущСствуСт – Ρ‚ΠΎ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌ случайный Π½ΠΎΠΌΠ΅Ρ€ 
    m_randomCrypto.GetBytes(transmissionId);
    key = new Tuple<EndPoint, Int32>(endPoint, BitConverter.ToInt32(transmissionId, 0));
    if (!m_listOfHandlers.TryAdd(key, new ReliableUdpConnectionRecord(key, this, reliableUdpMessage, asyncResult)))
      // Ссли снова Π½Π΅ ΡƒΠ΄Π°Π»ΠΎΡΡŒ – Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΡƒΠ΅ΠΌ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅
      throw new ArgumentException("Pair TransmissionId & EndPoint is already exists in the dictionary");
  }
  // запустили состояниС Π² ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ         
  m_listOfHandlers[key].State.SendPacket(m_listOfHandlers[key]);
}

ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° (состояниС FirstPacketSending):

public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{
  connectionRecord.PacketCounter = 0;
  connectionRecord.SndNext = 0;
  connectionRecord.WindowLowerBound = 0;       
  // ... 
  // создаСм Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ отправляСм Π΅Π³ΠΎ 
  ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord);
  ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header));
  // ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅ΠΌ счСтчик
  connectionRecord.SndNext++;
  // сдвигаСм окно
  connectionRecord.WindowLowerBound++;
  // ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΠΌ Π² состояниС SendingCycle
  connectionRecord.State = connectionRecord.Tcb.States.SendingCycle;
  // ЗапускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€
  connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
}

ПослС ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ΠΈΡ‚ Π² состояниС SendingCycle – ΠΎΠΆΠΈΠ΄Π°Ρ‚ΡŒ подтвСрТдСния ΠΎ доставкС ΠΏΠ°ΠΊΠ΅Ρ‚Π°.
Π‘Ρ‚ΠΎΡ€ΠΎΠ½Π°-ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚Π΅Π»ΡŒ, с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠ΅Ρ‚ΠΎΠ΄Π° EndReceive, ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚, создаСт Π½ΠΎΠ²ΡƒΡŽ connection record ΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Π΅Ρ‚ Π΄Π°Π½Π½Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚, с ΠΏΡ€Π΅Π΄Π²Π°Ρ€ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ распарсСнным Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠΌ, Π² ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρƒ ReceivePacket состояния FirstPacketReceived
Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ соСдинСния Π½Π° ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‰Π΅ΠΉ сторонС:

private void EndReceive(IAsyncResult ar)
{
  // ...
  // ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½
  // парсим Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚Π°        
  ReliableUdpHeader header;
  if (!ReliableUdpStateTools.ReadReliableUdpHeader(bytes, out header))
  {          
    // ΠΏΡ€ΠΈΡˆΠ΅Π» Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ - отбрасываСм Π΅Π³ΠΎ
    return;
  }
  // конструируСм ΠΊΠ»ΡŽΡ‡ для опрСдСлСния connection record’а для ΠΏΠ°ΠΊΠ΅Ρ‚Π°
  Tuple<EndPoint, Int32> key = new Tuple<EndPoint, Int32>(connectedClient, header.TransmissionId);
  // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ connection record ΠΈΠ»ΠΈ создаСм Π½ΠΎΠ²ΡƒΡŽ
  ReliableUdpConnectionRecord record = m_listOfHandlers.GetOrAdd(key, new ReliableUdpConnectionRecord(key, this, header. ReliableUdpMessageType));
  // запускаСм ΠΏΠ°ΠΊΠ΅Ρ‚ Π² ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ Π² ΠΊΠΎΠ½Π΅Ρ‡Π½Ρ‹ΠΉ Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚
  record.State.ReceivePacket(record, header, bytes);
}

ΠŸΡ€ΠΈΠ΅ΠΌ ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° ΠΈ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° подтвСрТдСния (состояниС FirstPacketReceived):

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket))
    // отбрасываСм ΠΏΠ°ΠΊΠ΅Ρ‚
    return;
  // ...
  // by design всС packet numbers Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‚ΡΡ с 0;
  if (header.PacketNumber != 0)          
    return;
  // ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠ΅ΠΌ массив для хранСния частСй сообщСния
  ReliableUdpStateTools.InitIncomingBytesStorage(connectionRecord, header);
  // записываСм Π΄Π°Π½Π½Ρ‹Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚ Π² массив
  ReliableUdpStateTools.WritePacketData(connectionRecord, header, payload);
  // считаСм ΠΊΠΎΠ»-Π²ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΡ€ΠΈΠΉΡ‚ΠΈ
  connectionRecord.NumberOfPackets = (int)Math.Ceiling((double) ((double) connectionRecord.IncomingStream.Length/(double) connectionRecord.BufferSize));
  // записываСм Π½ΠΎΠΌΠ΅Ρ€ послСднСго ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅Ρ‚Π° (0)
  connectionRecord.RcvCurrent = header.PacketNumber;
  // послС сдвинули ΠΎΠΊΠ½ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ° Π½Π° 1
  connectionRecord.WindowLowerBound++;
  // ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ состояниС
  connectionRecord.State = connectionRecord.Tcb.States.Assembling;  
  if (/*Ссли Π½Π΅ трСбуСтся ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅*/)
  // ...
  else
  {
    // отправляСм ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
    connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1);
  }
}

Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. Π—Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ соСдинСния ΠΏΠΎ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρƒ

ΠžΡ‚Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚ΠΎΠ² ваТная Ρ‡Π°ΡΡ‚ΡŒ Reliable UDP. Рассмотрим ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π½Π° ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹ΠΌ ΡƒΠ·Π»Π΅ ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ΅Π» сбой ΠΈ доставка Π΄Π°Π½Π½Ρ‹Ρ… Π² ΠΎΠ±ΠΎΠΈΡ… направлСния стала Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ.
Π”ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ° закрытия соСдинСния ΠΏΠΎ Ρ‚Π°ΠΉΠΌΡƒ-Π°ΡƒΡ‚Ρƒ:РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Как Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΡ‹, Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Ρƒ отправитСля Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ сразу послС ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ Π±Π»ΠΎΠΊΠ° ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². Π­Ρ‚ΠΎ происходит Π² ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ SendPacket состояния SendingCycle.
Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° (состояниС SendingCycle):

public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{      
  // отправляСм Π±Π»ΠΎΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²   
  // ...   
  // пСрСзапускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€ послС ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ
  connectionRecord.WaitForPacketsTimer.Change( connectionRecord.ShortTimerPeriod, -1 );
  if ( connectionRecord.CloseWaitTimer != null )
    connectionRecord.CloseWaitTimer.Change( -1, -1 );
}

ΠŸΠ΅Ρ€ΠΈΠΎΠ΄Ρ‹ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° Π·Π°Π΄Π°ΡŽΡ‚ΡΡ ΠΏΡ€ΠΈ создании соСдинСния. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ ShortTimerPeriod Ρ€Π°Π²Π΅Π½ 5 сСкундам. Π’ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΎΠ½ установлСн Π² 1,5 сСкунды.

Π£ входящСго соСдинСния Ρ‚Π°ΠΉΠΌΠ΅Ρ€ запускаСтся послС получСния послСднСго дошСдшСго ΠΏΠ°ΠΊΠ΅Ρ‚Π° Π΄Π°Π½Π½Ρ‹Ρ…, это происходит Π² ΠΌΠ΅Ρ‚ΠΎΠ΄Π΅ ReceivePacket состояния Assembling
Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° (состояниС Assembling):

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // ... 
  // пСрСзапускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€Ρ‹        
  connectionRecord.TimerSecondTry = false;
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // ...
}

Π’ΠΎ входящСм соСдинСнии Π·Π° врСмя оТидания Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° Π½Π΅ ΠΏΡ€ΠΈΡˆΠ»ΠΎ большС ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ². Π’Π°ΠΉΠΌΠ΅Ρ€ сработал ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Π» ΠΌΠ΅Ρ‚ΠΎΠ΄ ProcessPackets, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ Π±Ρ‹Π»ΠΈ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Ρ‹ потСрянныС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΈ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ€Π°Π· ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Ρ‹ запросы Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку.
ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° запросов Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку (состояниС Assembling):

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  // ...        
  if (/*ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° потСрянныС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ */)
  {
    // отправляСм запросы Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку
    // устанавливаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π²ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ Ρ€Π°Π·, для ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎΠΉ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠΈ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ
    if (!connectionRecord.TimerSecondTry)
    {
      connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
    connectionRecord.TimerSecondTry = true;
    return;
    }
  // Ссли послС Π΄Π²ΡƒΡ… ΠΏΠΎΠΏΡ‹Ρ‚ΠΎΠΊ срабатываний WaitForPacketTimer 
  // Π½Π΅ ΡƒΠ΄Π°Π»ΠΎΡΡŒ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ - запускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ соСдинСния
  StartCloseWaitTimer(connectionRecord);
  }
  else if (/*ΠΏΡ€ΠΈΡˆΠ΅Π» послСдний ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΈ ΡƒΡΠΏΠ΅ΡˆΠ½Π°Ρ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° */)
  {
    // ...
    StartCloseWaitTimer(connectionRecord);
  }
  // Ссли ack Π½Π° Π±Π»ΠΎΠΊ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π±Ρ‹Π» потСрян
  else
  { 
    if (!connectionRecord.TimerSecondTry)
    {
      // ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ отсылаСм ack
      connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
      connectionRecord.TimerSecondTry = true;
      return;
    }
    // запускаСм Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ соСдинСния
    StartCloseWaitTimer(connectionRecord);
  }
}

ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Π°Ρ TimerSecondTry ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΠ»Π°ΡΡŒ Π² true. Данная пСрСмСнная ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ Π·Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½Ρ‹ΠΉ пСрСзапуск Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€.

Π‘ΠΎ стороны отправитСля Ρ‚ΠΎΠΆΠ΅ срабатываСт Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ ΠΈ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ отсылаСтся послСдний ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚.
Π’ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° закрытия соСдинСния (состояниС SendingCycle):

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  // ...        
  // отправляСм ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ послСдний ΠΏΠ°ΠΊΠ΅Ρ‚ 
  // ...        
  // Π²ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ CloseWait – для оТидания восстановлСния соСдинСния ΠΈΠ»ΠΈ Π΅Π³ΠΎ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ
  StartCloseWaitTimer(connectionRecord);
}

ПослС Ρ‡Π΅Π³ΠΎ Π² исходящСм соСдинСнии запускаСтся Ρ‚Π°ΠΉΠΌΠ΅Ρ€ закрытия соСдинСния.
ReliableUdpState.StartCloseWaitTimer:

protected void StartCloseWaitTimer(ReliableUdpConnectionRecord connectionRecord)
{
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(connectionRecord.LongTimerPeriod, -1);
  else
    connectionRecord.CloseWaitTimer = new Timer(DisposeByTimeout, connectionRecord, connectionRecord.LongTimerPeriod, -1);
}

ΠŸΠ΅Ρ€ΠΈΠΎΠ΄ оТидания Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° закрытия соСдинСния Ρ€Π°Π²Π΅Π½ 30 сСкундам ΠΏΠΎ-ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ.

Π§Π΅Ρ€Π΅Π· Π½Π΅ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ врСмя, ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ срабатываСт Ρ€Π°Π±ΠΎΡ‡ΠΈΠΉ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π½Π° сторонС получатСля, вновь производится ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° запросов, послС Ρ‡Π΅Π³ΠΎ запускаСтся Ρ‚Π°ΠΉΠΌΠ΅Ρ€ закрытия соСдинСния Ρƒ входящСго соСдинСния

По ΡΡ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π½ΠΈΡŽ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ΠΎΠ² закрытия всС рСсурсы ΠΎΠ±ΠΎΠΈΡ… connection record ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°ΡŽΡ‚ΡΡ. ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ сообщаСт ΠΎ Π½Π΅ΡƒΠ΄Π°Ρ‡Π½ΠΎΠΉ доставкС Π²Ρ‹ΡˆΠ΅ΡΡ‚ΠΎΡΡ‰Π΅ΠΌΡƒ ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡŽ (см. API Reliable UDP).
ОсвобоТдСниС рСсурсов connection record'a:

public void Dispose()
{
  try
  {
    System.Threading.Monitor.Enter(this.LockerReceive);
  }
  finally
  {
    Interlocked.Increment(ref this.IsDone);
    if (WaitForPacketsTimer != null)
    {
      WaitForPacketsTimer.Dispose();
    }
    if (CloseWaitTimer != null)
    {
      CloseWaitTimer.Dispose();
    }
    byte[] stream;
    Tcb.IncomingStreams.TryRemove(Key, out stream);
    stream = null;
    Tcb.OutcomingStreams.TryRemove(Key, out stream);
    stream = null;
    System.Threading.Monitor.Exit(this.LockerReceive);
  }
}

Π“Π»ΡƒΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. ВосстановлСниС ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ…

Π”ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ° восстановлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΡ€ΠΈ ΠΏΠΎΡ‚Π΅Ρ€Π΅ ΠΏΠ°ΠΊΠ΅Ρ‚Π°:РСализация Reliable Udp ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° для .Net

Как ΡƒΠΆΠ΅ ΠΎΠ±ΡΡƒΠΆΠ΄Π°Π»ΠΎΡΡŒ Π² Π·Π°ΠΊΡ€Ρ‹Ρ‚ΠΈΠΈ соСдинСния ΠΏΠΎ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρƒ, ΠΏΠΎ ΠΈΡΡ‚Π΅Ρ‡Π΅Π½ΠΈΡŽ Ρ€Π°Π±ΠΎΡ‡Π΅Π³ΠΎ Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° Ρƒ получатСля ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° потСрянныС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹. Π’ случаС наличия ΠΏΠΎΡ‚Π΅Ρ€ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π±ΡƒΠ΄Π΅Ρ‚ составлСн список Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², Π½Π΅ Π΄ΠΎΡˆΠ΅Π΄ΡˆΠΈΡ… Π΄ΠΎ получатСля. Π”Π°Π½Π½Ρ‹Π΅ Π½ΠΎΠΌΠ΅Ρ€Π° заносятся Π² массив LostPackets ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ соСдинСния ΠΈ выполняСтся ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° запросов Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку.
ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° запросов Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² (состояниС Assembling):

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  //...
  if (!ReliableUdpStateTools.CheckForNoPacketLoss(connectionRecord, connectionRecord.IsLastPacketReceived != 0))
  {
    // Π΅ΡΡ‚ΡŒ потСрянныС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹, отсылаСм запросы Π½Π° Π½ΠΈΡ…
    foreach (int seqNum in connectionRecord.LostPackets)
    {
      if (seqNum != 0)
      {
        ReliableUdpStateTools.SendAskForLostPacket(connectionRecord, seqNum);
      }
    }
    // ...
  }
}

ΠžΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚Π΅Π»ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Ρ‚ запрос Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ доставку ΠΈ Π²Ρ‹ΡˆΠ»Π΅Ρ‚ Π½Π΅Π΄ΠΎΡΡ‚Π°ΡŽΡ‰ΠΈΠ΅ ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹. Π‘Ρ‚ΠΎΠΈΡ‚ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ Π² этот ΠΌΠΎΠΌΠ΅Π½Ρ‚ Ρƒ отправитСля ΡƒΠΆΠ΅ Π·Π°ΠΏΡƒΡ‰Π΅Π½ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ закрытия соСдинСния ΠΈ, ΠΏΡ€ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠΈ запроса, ΠΎΠ½ сбрасываСтся.
ΠŸΠΎΠ²Ρ‚ΠΎΡ€Π½Π°Ρ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠ° потСрянных ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² (состояниС SendingCycle):

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // ...
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  // сброс Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π° закрытия соСдинСния 
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // ...
  // это запрос Π½Π° ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Ρƒ – отправляСм Ρ‚Ρ€Π΅Π±ΡƒΠ΅ΠΌΡ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚          
  else
    ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord, header.PacketNumber));
}

ΠŸΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΎΡ‚ΠΏΡ€Π°Π²Π»Π΅Π½Π½Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ (packet#3 Π½Π° Π΄ΠΈΠ°Π³Ρ€Π°ΠΌΠΌΠ΅) принимаСтся входящим соСдинСниСм. ВыполняСтся ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° Π·Π°ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΎΠΊΠ½Π° ΠΏΡ€ΠΈΠ΅ΠΌΠ° ΠΈ обычная ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Π΄Π°Π½Π½Ρ‹Ρ… восстанавливаСтся.
ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° ΠΏΠΎΠΏΠ°Π΄Π°Π½ΠΈΠ΅ Π² ΠΎΠΊΠ½ΠΎ ΠΏΡ€ΠΈΠ΅ΠΌΠ° (состояниС Assembling):

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // ...
  // ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅ΠΌ счСтчик ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ²        
  connectionRecord.PacketCounter++;
  // записываСм Π² массив управлСния ΠΎΠΊΠ½ΠΎΠΌ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ Π½ΠΎΠΌΠ΅Ρ€ ΠΏΠ°ΠΊΠ΅Ρ‚Π°        
  connectionRecord.WindowControlArray[header.PacketNumber - connectionRecord.WindowLowerBound] = header.PacketNumber;
  // устанавливаСм наибольший ΠΏΡ€ΠΈΡˆΠ΅Π΄ΡˆΠΈΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚        
  if (header.PacketNumber > connectionRecord.RcvCurrent)
    connectionRecord.RcvCurrent = header.PacketNumber;
  // пСрСзапускам Ρ‚Π°ΠΉΠΌΠ΅Ρ€Ρ‹        
  connectionRecord.TimerSecondTry = false;
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // ...
  // Ссли Π½Π°ΠΌ ΠΏΡ€ΠΈΡˆΠ»ΠΈ всС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ΠΎΠΊΠ½Π°, Ρ‚ΠΎ сбрасываСм счСтчик
  // ΠΈ высылаСм ΠΏΠ°ΠΊΠ΅Ρ‚ ΠΏΠΎΠ΄Ρ‚Π²Π΅Ρ€ΠΆΠ΄Π΅Π½ΠΈΠ΅
  else if (connectionRecord.PacketCounter == connectionRecord.WindowSize)
  {
    // сбрасываСм счСтчик.      
    connectionRecord.PacketCounter = 0;
    // сдвинули ΠΎΠΊΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ
    connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
    // ΠΎΠ±Π½ΡƒΠ»Π΅Π½ΠΈΠ΅ массива управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ
    connectionRecord.WindowControlArray.Nullify();
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
  }
  // ...
}

API Reliable UDP

Для взаимодСйствия с ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»ΠΎΠΌ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ Π΄Π°Π½Π½Ρ‹Ρ… имССтся ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΉ класс Reliable Udp, ΡΠ²Π»ΡΡŽΡ‰ΠΈΠΉΡΡ ΠΎΠ±Π΅Ρ€Ρ‚ΠΊΠΎΠΉ Π½Π°Π΄ Π±Π»ΠΎΠΊΠΎΠΌ управлСния ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ΠΉ. Π’ΠΎΡ‚ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ Π²Π°ΠΆΠ½Ρ‹Π΅ Ρ‡Π»Π΅Π½Ρ‹ класса:

public sealed class ReliableUdp : IDisposable
{
  // ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ Π»ΠΎΠΊΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΊΠΎΠ½Π΅Ρ‡Π½ΡƒΡŽ Ρ‚ΠΎΡ‡ΠΊΡƒ
  public IPEndPoint LocalEndpoint    
  // создаСт экзСмпляр ReliableUdp ΠΈ запускаСт
  // ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Π½ΠΈΠ΅ входящих ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² Π½Π° ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΌ IP адрСсС
  // ΠΈ ΠΏΠΎΡ€Ρ‚Ρƒ. Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ 0 для ΠΏΠΎΡ€Ρ‚Π° ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ использованиС
  // динамичСски Π²Ρ‹Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ€Ρ‚Π°
  public ReliableUdp(IPAddress localAddress, int port = 0) 
  // подписка Π½Π° ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ входящих сообщСний
  public ReliableUdpSubscribeObject SubscribeOnMessages(ReliableUdpMessageCallback callback, ReliableUdpMessageTypes messageType = ReliableUdpMessageTypes.Any, IPEndPoint ipEndPoint = null)    
  // отписка ΠΎΡ‚ получСния сообщСний
  public void Unsubscribe(ReliableUdpSubscribeObject subscribeObject)
  // асинхронно ΠΎΡ‚ΠΏΡ€Π°Π²ΠΈΡ‚ΡŒ сообщСниС 
  // ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅: ΡΠΎΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌΠΎΡΡ‚ΡŒ с XP ΠΈ Server 2003 Π½Π΅ тСряСтся, Ρ‚.ΠΊ. ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ .NET Framework 4.0
  public Task<bool> SendMessageAsync(ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteEndPoint, CancellationToken cToken)
  // Π½Π°Ρ‡Π°Ρ‚ΡŒ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΡƒ сообщСния
  public IAsyncResult BeginSendMessage(ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteEndPoint, AsyncCallback asyncCallback, Object state)
  // ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ асинхронной ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ
  public bool EndSendMessage(IAsyncResult asyncResult)  
  // ΠΎΡ‡ΠΈΡΡ‚ΠΈΡ‚ΡŒ рСсурсы
  public void Dispose()    
}

ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ сообщСния осущСствляСтся ΠΏΠΎ подпискС. Π‘ΠΈΠ³Π½Π°Ρ‚ΡƒΡ€Π° Π΄Π΅Π»Π΅Π³Π°Ρ‚Π° для ΠΌΠ΅Ρ‚ΠΎΠ΄Π° ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π°:

public delegate void ReliableUdpMessageCallback( ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteClient );

Π‘ΠΎΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅:

public class ReliableUdpMessage
{
  // Ρ‚ΠΈΠΏ сообщСния, простоС пСрСчислСниС
  public ReliableUdpMessageTypes Type { get; private set; }
  // Π΄Π°Π½Π½Ρ‹Π΅ сообщСния
  public byte[] Body { get; private set; }
  // Ссли установлСно Π² true – ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ подтвСрТдСния доставки Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΡ‚ΠΊΠ»ΡŽΡ‡Π΅Π½
  // для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ сообщСния
  public bool NoAsk { get; private set; }
}

Для подписки Π½Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ сообщСний ΠΈ/ΠΈΠ»ΠΈ Π½Π° ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠ³ΠΎ отправитСля ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π΄Π²Π° Π½Π΅ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°: ReliableUdpMessageTypes messageType ΠΈ IPEndPoint ipEndPoint.

Π’ΠΈΠΏΡ‹ сообщСний:

public enum ReliableUdpMessageTypes : short
{ 
  // Π›ΡŽΠ±ΠΎΠ΅
  Any = 0,
  // Запрос ΠΊ STUN server 
  StunRequest = 1,
  // ΠžΡ‚Π²Π΅Ρ‚ ΠΎΡ‚ STUN server
  StunResponse = 2,
  // ΠŸΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° Ρ„Π°ΠΉΠ»Π°
  FileTransfer =3,
  // ...
}

ΠžΡ‚ΠΏΡ€Π°Π²ΠΊΠ° сообщСния осущСствляСтся асинхронного, для этого Π² ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π° асинхронная модСль программирования:

public IAsyncResult BeginSendMessage(ReliableUdpMessage reliableUdpMessage, IPEndPoint remoteEndPoint, AsyncCallback asyncCallback, Object state)

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ сообщСния Π±ΡƒΠ΄Π΅Ρ‚ true – Ссли сообщСниС ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎ дошло Π΄ΠΎ получатСля ΠΈ false – Ссли соСдинСниС Π±Ρ‹Π»ΠΎ Π·Π°ΠΊΡ€Ρ‹Ρ‚ΠΎ ΠΏΠΎ Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚Ρƒ:

public bool EndSendMessage(IAsyncResult asyncResult)

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

МногоС Π½Π΅ Π±Ρ‹Π»ΠΎ описано Π² Ρ€Π°ΠΌΠΊΠ°Ρ… Π΄Π°Π½Π½ΠΎΠΉ ΡΡ‚Π°Ρ‚ΡŒΠΈ. ΠœΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡ‹ согласования ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ², ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ ΠΈ ошибок, рСализация асинхронных ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ сообщСния. Но ядро ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°, описаниС Π»ΠΎΠ³ΠΈΠΊΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ², установка соСдинСния ΠΈ ΠΎΡ‚Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° Ρ‚Π°ΠΉΠΌ-Π°ΡƒΡ‚ΠΎΠ², Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΡ€ΠΎΡΡΠ½ΠΈΡ‚ΡŒΡΡ для Вас.

ΠŸΡ€ΠΎΠ΄Π΅ΠΌΠΎΠ½ΡΡ‚Ρ€ΠΈΡ€ΠΎΠ²Π°Π½Π½Π°Ρ вСрсия ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠΉ доставки достаточно устойчива ΠΈ Π³ΠΈΠ±ΠΊΠ°, ΠΈ соотвСтствуСт ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹ΠΌ Ρ€Π°Π½Π΅Π΅ трСбованиям. Но я Ρ…ΠΎΡ‡Ρƒ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ описанная рСализация ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΡƒΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΡΡ‚ΠΎΠ²Π°Π½Π°. К ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ, для увСличСния пропускной способности ΠΈ динамичСского измСнСния ΠΏΠ΅Ρ€ΠΈΠΎΠ΄ΠΎΠ² Ρ‚Π°ΠΉΠΌΠ΅Ρ€ΠΎΠ² Π² ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ» ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ Ρ‚Π°ΠΊΠΈΠ΅ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡ‹ ΠΊΠ°ΠΊ sliding window ΠΈ RTT, Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΌ рСализация ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° опрСдСлСния MTU ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ соСдинСния (Π½ΠΎ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² случаС ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ Π±ΠΎΠ»ΡŒΡˆΠΈΡ… сообщСний).

Бпасибо Π·Π° Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, ΠΆΠ΄Ρƒ Π’Π°ΡˆΠΈΡ… ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠ΅Π² ΠΈ Π·Π°ΠΌΠ΅Ρ‡Π°Π½ΠΈΠΉ.

P.S. Для Ρ‚Π΅Ρ…, ΠΊΡ‚ΠΎ интСрСсуСтся подробностями ΠΈΠ»ΠΈ просто Ρ…ΠΎΡ‡Π΅Ρ‚ ΠΏΡ€ΠΎΡ‚Π΅ΡΡ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ», ссылка Π½Π° ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Π½Π° GitHube:
ΠŸΡ€ΠΎΠ΅ΠΊΡ‚ Reliable UDP

ΠŸΠΎΠ»Π΅Π·Π½Ρ‹Π΅ ссылки ΠΈ ΡΡ‚Π°Ρ‚ΡŒΠΈ

  1. БпСцификация ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° TCP: Π½Π° английском ΠΈ Π½Π° русском
  2. БпСцификация ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π° UDP: Π½Π° английском ΠΈ Π½Π° русском
  3. ΠžΠ±ΡΡƒΠΆΠ΄Π΅Π½ΠΈΠ΅ RUDP ΠΏΡ€ΠΎΡ‚ΠΎΠΊΠΎΠ»Π°: draft-ietf-sigtran-reliable-udp-00
  4. Reliable Data Protocol: rfc 908 ΠΈ rfc 1151
  5. ΠŸΡ€ΠΎΡΡ‚Π°Ρ рСализация подтвСрТдСния доставки ΠΏΠΎ UDP: Take Total Control Of Your Networking With .NET And UDP
  6. Π‘Ρ‚Π°Ρ‚ΡŒΡ, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰Π°Ρ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΡ‹ прСодолСния NAT’ΠΎΠ²: Peer-to-Peer Communication Across Network Address Translators
  7. РСализация асинхронной ΠΌΠΎΠ΄Π΅Π»ΠΈ программирования: Implementing the CLR Asynchronous Programming Model ΠΈ How to implement the IAsyncResult design pattern
  8. ΠŸΠ΅Ρ€Π΅Π½ΠΎΡ асинхронной ΠΌΠΎΠ΄Π΅Π»ΠΈ программирования Π² асинхронный шаблон, основанный Π½Π° Π·Π°Π΄Π°Ρ‡Π°Ρ… (APM Π² TAP):
    TPL and Traditional .NET Asynchronous Programming
    Interop with Other Asynchronous Patterns and Types

Update: Бпасибо mayorovp ΠΈ sidristij Π·Π° идСю добавлСния task’Π° ΠΊ интСрфСйсу. Π‘ΠΎΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌΠΎΡΡ‚ΡŒ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ со старыми ОБ Π½Π΅ Π½Π°Ρ€ΡƒΡˆΠ°Π΅Ρ‚ΡΡ, Ρ‚.ΠΊ. 4-Ρ‹ΠΉ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΈ XP ΠΈ 2003 server.

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