ΠΠ½ΡΠ΅ΡΠ½Π΅Ρ Π΄Π°Π²Π½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΠ»ΡΡ. ΠΠ΄ΠΈΠ½ ΠΈΠ· ΠΎΡΠ½ΠΎΠ²Π½ΡΡ
ΠΏΡΠΎΡΠΎΠΊΠΎΠ»ΠΎΠ² ΠΠ½ΡΠ΅ΡΠ½Π΅ΡΠ° β UDP ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΠΌ Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ Π΄Π»Ρ Π΄ΠΎΡΡΠ°Π²ΠΊΠΈ Π΄Π΅ΠΉΡΠ°Π³ΡΠ°ΠΌΠΌ ΠΈ ΡΠΈΡΠΎΠΊΠΎΠ²Π΅ΡΠ°ΡΠ΅Π»ΡΠ½ΡΡ
ΡΠ°ΡΡΡΠ»ΠΎΠΊ, Π½ΠΎ ΠΈ Π΄Π»Ρ ΠΎΠ±Π΅ΡΠΏΠ΅ΡΠ΅Π½ΠΈΡ Β«peer-to-peerΒ» ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ ΠΌΠ΅ΠΆΠ΄Ρ ΡΠ·Π»Π°ΠΌΠΈ ΡΠ΅ΡΠΈ. ΠΠ²ΠΈΠ΄Ρ ΡΠ²ΠΎΠ΅Π³ΠΎ ΠΏΡΠΎΡΡΠΎΠ³ΠΎ ΡΡΡΡΠΎΠΉΡΡΠ²Π°, Ρ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π° ΠΏΠΎΡΠ²ΠΈΠ»ΠΎΡΡ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ Π½Π΅ Π·Π°ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²Π°Π½Π½ΡΡ
ΡΠ°Π½Π΅Π΅ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ, ΠΏΡΠ°Π²Π΄Π°, Π½Π΅Π΄ΠΎΡΡΠ°ΡΠΊΠΈ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π°, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ ΠΎΡΡΡΡΡΡΠ²ΠΈΠ΅ Π³Π°ΡΠ°Π½ΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΉ Π΄ΠΎΡΡΠ°Π²ΠΊΠΈ, Π½ΠΈΠΊΡΠ΄Π° ΠΏΡΠΈ ΡΡΠΎΠΌ Π½Π΅ ΠΈΡΡΠ΅Π·Π»ΠΈ. Π ΡΡΠΎΠΉ ΡΡΠ°ΡΡΠ΅ ΠΎΠΏΠΈΡΡΠ²Π°Π΅ΡΡΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π° Π³Π°ΡΠ°Π½ΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΉ Π΄ΠΎΡΡΠ°Π²ΠΊΠΈ ΠΏΠΎΠ²Π΅ΡΡ
UDP.
Π‘ΠΎΠ΄Π΅ΡΠΆΠ°Π½ΠΈΠ΅:
ΠΠ΅ΡΠΎΠ΄ DisposeByTimeout ΠΠ΅ΡΠΎΠ΄ ProcessPackets ΠΠ΅ΡΠΎΠ΄ ReceivePacket ΠΠ΅ΡΠΎΠ΄ SendPacket
ΠΡΡΡΠΏΠ»Π΅Π½ΠΈΠ΅
ΠΠ΅ΡΠ²ΠΎΠ½Π°ΡΠ°Π»ΡΠ½Π°Ρ Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΠ° ΠΠ½ΡΠ΅ΡΠ½Π΅ΡΠ° ΠΏΠΎΠ΄ΡΠ°Π·ΡΠΌΠ΅Π²Π°Π»Π° ΠΎΠ΄Π½ΠΎΡΠΎΠ΄Π½ΠΎΠ΅ Π°Π΄ΡΠ΅ΡΠ½ΠΎΠ΅ ΠΏΡΠΎΡΡΡΠ°Π½ΡΡΠ²ΠΎ, Π² ΠΊΠΎΡΠΎΡΠΎΠΌ ΠΊΠ°ΠΆΠ΄ΡΠΉ ΡΠ·Π΅Π» ΠΈΠΌΠ΅Π» Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠΉ ΠΈ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΡΠΉ IP Π°Π΄ΡΠ΅Ρ, ΠΈ ΠΌΠΎΠ³ Π½Π°ΠΏΡΡΠΌΡΡ ΠΎΠ±ΡΠ°ΡΡΡΡ Ρ Π΄ΡΡΠ³ΠΈΠΌΠΈ ΡΠ·Π»Π°ΠΌΠΈ. Π‘Π΅ΠΉΡΠ°Ρ ΠΠ½ΡΠ΅ΡΠ½Π΅Ρ, ΠΏΠΎ ΡΠ°ΠΊΡΡ, ΠΈΠΌΠ΅Π΅Ρ Π΄ΡΡΠ³ΡΡ Π°ΡΡ
ΠΈΡΠ΅ΠΊΡΡΡΡ β ΠΎΠ΄Π½Ρ ΠΎΠ±Π»Π°ΡΡΡ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΡ
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 Π±ΡΠ΄Π΅Ρ ΠΎΠΏΠΈΡΠ°Π½Π° Π² ΡΠ»Π΅Π΄ΡΡΡΠΈΡ ΡΡΠ°ΡΡΡΡ .
Π’ΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΡ ΠΊ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Ρ
- ΠΠ°Π΄Π΅ΠΆΠ½Π°Ρ Π΄ΠΎΡΡΠ°Π²ΠΊΠ° ΠΏΠ°ΠΊΠ΅ΡΠΎΠ², ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Π½Π°Ρ ΡΠ΅ΡΠ΅Π· ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌ ΠΏΠΎΠ»ΠΎΠΆΠΈΡΠ΅Π»ΡΠ½ΠΎΠΉ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠΉ ΡΠ²ΡΠ·ΠΈ (ΡΠ°ΠΊ Π½Π°Π·ΡΠ²Π°Π΅ΠΌΡΠΉ positive acknowledgment )
- ΠΠ΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎΡΡΡ ΡΡΡΠ΅ΠΊΡΠΈΠ²Π½ΠΎΠΉ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π±ΠΎΠ»ΡΡΠΈΡ Π΄Π°Π½Π½ΡΡ , Ρ.Π΅. ΠΏΡΠΎΡΠΎΠΊΠΎΠ» Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΈΠ·Π±Π΅Π³Π°ΡΡ Π»ΠΈΡΠ½ΠΈΡ ΡΠ΅ΡΡΠ°Π½ΡΠ»ΡΡΠΈΠΉ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ²
- ΠΠΎΠ»ΠΆΠ½Π° Π±ΡΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΠΎΡΠΌΠ΅Π½Ρ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌΠ° ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ Π΄ΠΎΡΡΠ°Π²ΠΊΠΈ ( Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½ΠΈΡΠΎΠ²Π°ΡΡ ΠΊΠ°ΠΊ Β«ΡΠΈΡΡΡΠΉΒ» UDP ΠΏΡΠΎΡΠΎΠΊΠΎΠ»)
- ΠΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π½ΠΎΠ³ΠΎ ΡΠ΅ΠΆΠΈΠΌΠ°, Ρ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠ΅ΠΌ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ
- ΠΠ°Π·ΠΎΠ²ΠΎΠΉ Π΅Π΄ΠΈΠ½ΠΈΡΠ΅ΠΉ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π΄Π°Π½Π½ΡΡ ΠΏΠΎ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Ρ Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅
ΠΡΠΈ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΡ Π²ΠΎ ΠΌΠ½ΠΎΠ³ΠΎΠΌ ΡΠΎΠ²ΠΏΠ°Π΄Π°ΡΡ Ρ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΡΠΌΠΈ ΠΊ Reliable Data Protocol, ΠΎΠΏΠΈΡΠ°Π½Π½ΡΠΌΠΈ Π²
ΠΠ»Ρ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΡ Π΄Π°Π½Π½ΡΡ
ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΠΉ, Π΄Π°Π²Π°ΠΉΡΠ΅ ΡΠ°ΡΡΠΌΠΎΡΡΠΈΠΌ Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ Π΄ΠΈΠ°Π³ΡΠ°ΠΌΠΌΡ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π΄Π°Π½Π½ΡΡ
ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²ΡΠΌΡ ΡΠ·Π»Π°ΠΌΠΈ ΡΠ΅ΡΠΈ ΠΏΠΎ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π°ΠΌ TCP ΠΈ UDP. ΠΡΡΡΡ Π² ΠΎΠ±ΠΎΠΈΡ
ΡΠ»ΡΡΠ°ΡΡ
Ρ Π½Π°Ρ Π±ΡΠ΄Π΅Ρ ΠΏΠΎΡΠ΅ΡΡΠ½ ΠΎΠ΄ΠΈΠ½ ΠΏΠ°ΠΊΠ΅Ρ.
ΠΠ΅ΡΠ΅Π΄Π°ΡΠ° Π½Π΅ΠΈΠ½ΡΠ΅ΡΠ°ΠΊΡΠΈΠ²Π½ΡΡ
Π΄Π°Π½Π½ΡΡ
ΠΏΠΎ TCP:
ΠΠ°ΠΊ Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· Π΄ΠΈΠ°Π³ΡΠ°ΠΌΠΌΡ, Π² ΡΠ»ΡΡΠ°Π΅ ΠΏΠΎΡΠ΅ΡΠΈ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ², TCP ΠΎΠ±Π½Π°ΡΡΠΆΠΈΡ ΠΏΠΎΡΠ΅ΡΡΠ½Π½ΡΠΉ ΠΏΠ°ΠΊΠ΅Ρ ΠΈ ΡΠΎΠΎΠ±ΡΠΈΡ ΠΎΠ± ΡΡΠΎΠΌ ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ, Π·Π°ΠΏΡΠΎΡΠΈΠ² Π½ΠΎΠΌΠ΅Ρ ΠΏΠΎΡΠ΅ΡΡΠ½Π½ΠΎΠ³ΠΎ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠ°.
ΠΠ΅ΡΠ΅Π΄Π°ΡΠ° Π΄Π°Π½Π½ΡΡ
ΠΏΠΎ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Ρ UDP:
UDP Π½Π΅ ΠΏΡΠ΅Π΄ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ Π½ΠΈΠΊΠ°ΠΊΠΈΡ
ΡΠ°Π³ΠΎΠ² ΠΏΠΎ ΠΎΠ±Π½Π°ΡΡΠΆΠ΅Π½ΠΈΡ ΠΏΠΎΡΠ΅ΡΡ. ΠΠΎΠ½ΡΡΠΎΠ»Ρ ΠΎΡΠΈΠ±ΠΎΠΊ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π² UDP ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π΅ ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ Π²ΠΎΠ·Π»Π°Π³Π°Π΅ΡΡΡ Π½Π° ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅.
ΠΠ±Π½Π°ΡΡΠΆΠ΅Π½ΠΈΠ΅ ΠΎΡΠΈΠ±ΠΎΠΊ Π² TCP ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π΅ Π΄ΠΎΡΡΠΈΠ³Π°Π΅ΡΡΡ Π±Π»Π°Π³ΠΎΠ΄Π°ΡΡ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Ρ ΠΊΠΎΠ½Π΅ΡΠ½ΡΠΌ ΡΠ·Π»ΠΎΠΌ, ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ ΡΡΠΎΠ³ΠΎ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ, ΡΠΊΠ°Π·Π°Π½ΠΈΡ Π½ΠΎΠΌΠ΅ΡΠ° ΠΎΡΠΏΡΠ°Π²Π»Π΅Π½Π½ΡΡ Π±Π°ΠΉΡ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΌ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ΅ ΠΏΠ°ΠΊΠ΅ΡΠ°, ΠΈ ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΡΡ ΠΎ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Π½ΠΎΠΌΠ΅ΡΠ° ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ Β«acknowledge numberΒ».
ΠΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ, Π΄Π»Ρ ΠΏΠΎΠ²ΡΡΠ΅Π½ΠΈΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½ΠΎΡΡΠΈ (Ρ.Π΅. ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠ° Π±Π΅Π· ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ) TCP ΠΏΡΠΎΡΠΎΠΊΠΎΠ» ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅Ρ ΡΠ°ΠΊ Π½Π°Π·ΡΠ²Π°Π΅ΠΌΠΎΠ΅ ΠΎΠΊΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ β ΡΠΈΡΠ»ΠΎ Π±Π°ΠΉΡ Π΄Π°Π½Π½ΡΡ ΠΊΠΎΡΠΎΡΡΠ΅ ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠ° ΠΎΠΆΠΈΠ΄Π°Π΅Ρ ΠΏΡΠΈΠ½ΡΡΡ.
ΠΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ Ρ TCP ΠΏΡΠΎΡΠΎΠΊΠΎΠ»ΠΎΠΌ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡΡΡΡ Π²
ΠΠ· Π²ΡΡΠ΅ΠΎΠΏΠΈΡΠ°Π½Π½ΠΎΠ³ΠΎ, ΠΏΠΎΠ½ΡΡΠ½ΠΎ, ΡΡΠΎ Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠ³ΠΎ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π° Π΄ΠΎΡΡΠ°Π²ΠΊΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ ΠΏΠΎΠ²Π΅ΡΡ UDP (Π² Π΄Π°Π»ΡΠ½Π΅ΠΉΡΠ΅ΠΌ Π±ΡΠ΄Π΅ΠΌ Π½Π°Π·ΡΠ²Π°ΡΡ Reliable UDP), ΡΡΠ΅Π±ΡΠ΅ΡΡΡ ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°ΡΡ ΡΡ ΠΎΠΆΠΈΠ΅ Ρ TCP ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌΡ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π΄Π°Π½Π½ΡΡ . Π ΠΈΠΌΠ΅Π½Π½ΠΎ:
- ΡΠΎΡ ΡΠ°Π½ΡΡΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ
- ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π½ΡΠΌΠ΅ΡΠ°ΡΠΈΡ ΡΠ΅Π³ΠΌΠ΅Π½ΡΠΎΠ²
- ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ
- ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠΏΡΠΎΡΠ΅Π½Π½ΡΠΉ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌ ΠΎΠΊΠ½Π°, Π΄Π»Ρ ΡΠ²Π΅Π»ΠΈΡΠ΅Π½ΠΈΡ ΠΏΡΠΎΠΏΡΡΠΊΠ½ΠΎΠΉ ΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡΠΈ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π°
ΠΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ, ΡΡΠ΅Π±ΡΠ΅ΡΡΡ:
- ΡΠΈΠ³Π½Π°Π»ΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ ΠΎ Π½Π°ΡΠ°Π»Π΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ, Π΄Π»Ρ Π²ΡΠ΄Π΅Π»Π΅Π½ΠΈΡ ΡΠ΅ΡΡΡΡΠΎΠ² ΠΏΠΎΠ΄ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅
- ΡΠΈΠ³Π½Π°Π»ΠΈΠ·ΠΈΡΠΎΠ²Π°ΡΡ ΠΎΠ± ΠΎΠΊΠΎΠ½ΡΠ°Π½ΠΈΠΈ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ, Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ Π²ΡΡΠ΅ΡΡΠΎΡΡΠ΅ΠΌΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΈ Π²ΡΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π΅Π½ΠΈΡ ΡΠ΅ΡΡΡΡΠΎΠ² ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π°
- ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Ρ Π΄Π»Ρ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ ΠΎΡΠΊΠ»ΡΡΠ°ΡΡ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠΉ Π΄ΠΎΡΡΠ°Π²ΠΊΠΈ, ΡΡΠΎΠ±Ρ ΡΡΠ½ΠΊΡΠΈΠΎΠ½ΠΈΡΠΎΠ²Π°ΡΡ ΠΊΠ°ΠΊ Β«ΡΠΈΡΡΡΠΉΒ» UDP
ΠΠ°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ Reliable UDP
ΠΡΠΏΠΎΠΌΠ½ΠΈΠΌ, ΡΡΠΎ UDP Π΄Π΅ΠΉΡΠ°Π³ΡΠ°ΠΌΠΌΠ° ΠΈΠ½ΠΊΠ°ΠΏΡΡΠ»ΠΈΡΡΠ΅ΡΡΡ Π² IP Π΄Π΅ΠΉΡΠ°Π³ΡΠ°ΠΌΠΌΡ. ΠΠ°ΠΊΠ΅Ρ Reliable UDP ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²Π΅Π½Π½ΠΎ Β«Π·Π°Π²ΠΎΡΠ°ΡΠΈΠ²Π°Π΅ΡΡΡΒ» Π² UDP Π΄Π΅ΠΉΡΠ°Π³ΡΠ°ΠΌΠΌΡ.
ΠΠ½ΠΊΠ°ΠΏΡΡΠ»ΡΡΠΈΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° Reliable UDP:
Π‘ΡΡΡΠΊΡΡΡΠ° Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° Reliable UDP Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ ΠΏΡΠΎΡΡΠ°Ρ:
- Flags β ΡΠΏΡΠ°Π²Π»ΡΡΡΠΈΠ΅ ΡΠ»Π°Π³ΠΈ ΠΏΠ°ΠΊΠ΅ΡΠ°
- MessageType β ΡΠΈΠΏ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π²ΡΡΠ΅ΡΡΠΎΡΡΠΈΠΌΠΈ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡΠΌΠΈ, Π΄Π»Ρ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ Π½Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ
- TransmissionId β Π½ΠΎΠΌΠ΅Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ, Π²ΠΌΠ΅ΡΡΠ΅ Ρ Π°Π΄ΡΠ΅ΡΠΎΠΌ ΠΈ ΠΏΠΎΡΡΠΎΠΌ ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ ΡΠ½ΠΈΠΊΠ°Π»ΡΠ½ΠΎ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅
- PacketNumber β Π½ΠΎΠΌΠ΅Ρ ΠΏΠ°ΠΊΠ΅ΡΠ°
- Options β Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΎΠΏΡΠΈΠΈ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π°. Π ΡΠ»ΡΡΠ°Π΅ ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠ° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π΄Π»Ρ ΡΠΊΠ°Π·Π°Π½ΠΈΡ ΡΠ°Π·ΠΌΠ΅ΡΠ° ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ
Π€Π»Π°Π³ΠΈ Π±ΡΠ²Π°ΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅:
- FirstPacket β ΠΏΠ΅ΡΠ²ΡΠΉ ΠΏΠ°ΠΊΠ΅Ρ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ
- NoAsk β ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ Π½Π΅ ΡΡΠ΅Π±ΡΠ΅Ρ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΡ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌΠ° ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ
- LastPacket β ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ ΠΏΠ°ΠΊΠ΅Ρ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ
- RequestForPacket β ΠΏΠ°ΠΊΠ΅Ρ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ ΠΈΠ»ΠΈ Π·Π°ΠΏΡΠΎΡ Π½Π° ΠΏΠΎΡΠ΅ΡΡΠ½Π½ΡΠΉ ΠΏΠ°ΠΊΠ΅Ρ
ΠΠ±ΡΠΈΠ΅ ΠΏΡΠΈΠ½ΡΠΈΠΏΡ ΡΠ°Π±ΠΎΡΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π°
Π’Π°ΠΊ ΠΊΠ°ΠΊ Reliable UDP ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠΎΠ²Π°Π½ Π½Π° Π³Π°ΡΠ°Π½ΡΠΈΡΠΎΠ²Π°Π½Π½ΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΠΌΠ΅ΠΆΠ΄Ρ Π΄Π²ΡΠΌΡ ΡΠ·Π»Π°ΠΌΠΈ, ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΌΠ΅ΡΡ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°ΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ Ρ Π΄ΡΡΠ³ΠΎΠΉ ΡΡΠΎΡΠΎΠ½ΠΎΠΉ. ΠΠ»Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΡΡΠΎΡΠΎΠ½Π°-ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ ΠΏΠΎΡΡΠ»Π°Π΅Ρ ΠΏΠ°ΠΊΠ΅Ρ Ρ ΡΠ»Π°Π³ΠΎΠΌ FirstPacket, ΠΎΡΠ²Π΅Ρ Π½Π° ΠΊΠΎΡΠΎΡΡΠΉ Π±ΡΠ΄Π΅Ρ ΠΎΠ·Π½Π°ΡΠ°ΡΡ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ. ΠΡΠ΅ ΠΎΡΠ²Π΅ΡΠ½ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ, ΠΈΠ»ΠΈ, ΠΏΠΎ-Π΄ΡΡΠ³ΠΎΠΌΡ, ΠΏΠ°ΠΊΠ΅ΡΡ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ, Π²ΡΠ΅Π³Π΄Π° Π²ΡΡΡΠ°Π²Π»ΡΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ»Ρ PacketNumber Π½Π° Π΅Π΄ΠΈΠ½ΠΈΡΡ Π±ΠΎΠ»ΡΡΠ΅, ΡΠ΅ΠΌ ΡΠ°ΠΌΠΎΠ΅ Π±ΠΎΠ»ΡΡΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ PacketNumber Ρ ΡΡΠΏΠ΅ΡΠ½ΠΎ ΠΏΡΠΈΡΠ΅Π΄ΡΠΈΡ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ². Π ΠΏΠΎΠ»Π΅ Options Π΄Π»Ρ ΠΏΠ΅ΡΠ²ΠΎΠ³ΠΎ ΠΎΡΠΏΡΠ°Π²Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠ° Π·Π°ΠΏΠΈΡΡΠ²Π°Π΅ΡΡΡ ΡΠ°Π·ΠΌΠ΅Ρ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ.
ΠΠ»Ρ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΏΠΎΡ
ΠΎΠΆΠΈΠΉ ΠΌΠ΅Ρ
Π°Π½ΠΈΠ·ΠΌ. Π ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅ΠΌ ΠΏΠ°ΠΊΠ΅ΡΠ΅ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΡΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅ΡΡΡ ΡΠ»Π°Π³ LastPacket. Π ΠΎΡΠ²Π΅ΡΠ½ΠΎΠΌ ΠΏΠ°ΠΊΠ΅ΡΠ΅ ΡΠΊΠ°Π·ΡΠ²Π°Π΅ΡΡΡ Π½ΠΎΠΌΠ΅Ρ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠ° + 1, ΡΡΠΎ Π΄Π»Ρ ΠΏΡΠΈΡΠΌΠ½ΠΎΠΉ ΡΡΠΎΡΠΎΠ½Ρ ΠΎΠ·Π½Π°ΡΠ°Π΅Ρ ΡΡΠΏΠ΅ΡΠ½ΡΡ Π΄ΠΎΡΡΠ°Π²ΠΊΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ.
ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΈ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ:
ΠΠΎΠ³Π΄Π° ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΎ, Π½Π°ΡΠΈΠ½Π°Π΅ΡΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠ° Π΄Π°Π½Π½ΡΡ
. ΠΠ°Π½Π½ΡΠ΅ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ Π±Π»ΠΎΠΊΠ°ΠΌΠΈ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ². ΠΠ°ΠΆΠ΄ΡΠΉ Π±Π»ΠΎΠΊ, ΠΊΡΠΎΠΌΠ΅ ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ, ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ². ΠΠ½ΠΎ ΡΠ°Π²Π½ΠΎ ΡΠ°Π·ΠΌΠ΅ΡΡ ΠΎΠΊΠ½Π° ΠΏΡΠΈΠ΅ΠΌΠ°/ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ. ΠΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ Π±Π»ΠΎΠΊ Π΄Π°Π½Π½ΡΡ
ΠΌΠΎΠΆΠ΅Ρ ΠΈΠΌΠ΅ΡΡ ΠΌΠ΅Π½ΡΡΠ΅Π΅ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ². ΠΠΎΡΠ»Π΅ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π±Π»ΠΎΠΊΠ°, ΡΡΠΎΡΠΎΠ½Π°-ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ ΠΎ Π΄ΠΎΡΡΠ°Π²ΠΊΠ΅, Π»ΠΈΠ±ΠΎ Π·Π°ΠΏΡΠΎΡΠ° Π½Π° ΠΏΠΎΠ²ΡΠΎΡΠ½ΡΡ Π΄ΠΎΡΡΠ°Π²ΠΊΡ ΠΏΠΎΡΠ΅ΡΡΠ½Π½ΡΡ
ΠΏΠ°ΠΊΠ΅ΡΠΎΠ², ΠΎΡΡΠ°Π²Π»ΡΡ ΠΎΡΠΊΡΡΡΡΠΌ ΠΎΠΊΠ½ΠΎ ΠΏΡΠΈΠ΅ΠΌΠ°/ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π΄Π»Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ ΠΎΡΠ²Π΅ΡΠΎΠ². ΠΠΎΡΠ»Π΅ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ ΠΎ Π΄ΠΎΡΡΠ°Π²ΠΊΠ΅ Π±Π»ΠΎΠΊΠ°, ΠΎΠΊΠ½ΠΎ ΠΏΡΠΈΠ΅ΠΌ/ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ ΡΠ΄Π²ΠΈΠ³Π°Π΅ΡΡΡ ΠΈ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΡΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ Π±Π»ΠΎΠΊ Π΄Π°Π½Π½ΡΡ
.
Π‘ΡΠΎΡΠΎΠ½Π°-ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ ΠΏΠ°ΠΊΠ΅ΡΡ. ΠΠ°ΠΆΠ΄ΡΠΉ ΠΏΠ°ΠΊΠ΅Ρ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΡΡΡ Π½Π° ΠΏΠΎΠΏΠ°Π΄Π°Π½ΠΈΠ΅ Π² ΠΎΠΊΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ. ΠΠ΅ ΠΏΠΎΠΏΠ°Π΄Π°ΡΡΠΈΠ΅ Π² ΠΎΠΊΠ½ΠΎ ΠΏΠ°ΠΊΠ΅ΡΡ ΠΈ Π΄ΡΠ±Π»ΠΈΠΊΠ°ΡΡ ΠΎΡΡΠ΅ΠΈΠ²Π°ΡΡΡΡ. Π’.ΠΊ. ΡΠ°Π·ΠΌΠ΅Ρ ΠΎΠΊΠ½Π° ΡΡΠΎΡΠΎΠ³ΠΎ ΡΠΈΠΊΡΠΈΡΠΎΠ²Π°Π½ ΠΈ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ² Ρ ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ ΠΈ Ρ ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ, ΡΠΎ Π² ΡΠ»ΡΡΠ°Π΅ Π΄ΠΎΡΡΠ°Π²ΠΊΠΈ Π±Π»ΠΎΠΊΠ° ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² Π±Π΅Π· ΠΏΠΎΡΠ΅ΡΡ, ΠΎΠΊΠ½ΠΎ ΡΠ΄Π²ΠΈΠ³Π°Π΅ΡΡΡ Π΄Π»Ρ ΠΏΡΠΈΠ΅ΠΌΠ° ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² ΡΠ»Π΅Π΄ΡΡΡΠ΅Π³ΠΎ Π±Π»ΠΎΠΊΠ° Π΄Π°Π½Π½ΡΡ
ΠΈ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΡΡΡ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΠ΅ ΠΎ Π΄ΠΎΡΡΠ°Π²ΠΊΠ΅. ΠΡΠ»ΠΈ ΠΎΠΊΠ½ΠΎ Π½Π΅ Π·Π°ΠΏΠΎΠ»Π½ΠΈΡΡΡ Π·Π° ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½Π½ΡΠΉ ΡΠ°Π±ΠΎΡΠΈΠΌ ΡΠ°ΠΉΠΌΠ΅ΡΠΎΠΌ ΠΏΠ΅ΡΠΈΠΎΠ΄, ΡΠΎ Π±ΡΠ΄Π΅Ρ Π·Π°ΠΏΡΡΠ΅Π½Π° ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° ΡΠΎ, ΠΊΠ°ΠΊΠΈΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ Π½Π΅ Π±ΡΠ»ΠΈ Π΄ΠΎΡΡΠ°Π²Π»Π΅Π½Ρ ΠΈ Π±ΡΠ΄ΡΡ ΠΎΡΠΏΡΠ°Π²Π»Π΅Π½Ρ Π·Π°ΠΏΡΠΎΡΡ Π½Π° ΠΏΠΎΠ²ΡΠΎΡΠ½ΡΡ Π΄ΠΎΡΡΠ°Π²ΠΊΡ.
ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° ΠΏΠΎΠ²ΡΠΎΡΠ½ΠΎΠΉ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ:
Π’Π°ΠΉΠΌ-Π°ΡΡΡ ΠΈ ΡΠ°ΠΉΠΌΠ΅ΡΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π°
Π‘ΡΡΠ΅ΡΡΠ²ΡΠ΅Ρ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈΡΠΈΠ½, ΠΏΠΎ ΠΊΠΎΡΠΎΡΡΠΌ Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΎ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π΅ΡΠ»ΠΈ ΠΏΡΠΈΠ½ΠΈΠΌΠ°ΡΡΠ°Ρ ΡΡΠΎΡΠΎΠ½Π° Π²Π½Π΅ ΡΠ΅ΡΠΈ. Π ΡΠ°ΠΊΠΎΠΌ ΡΠ»ΡΡΠ°Π΅, ΠΏΡΠΈ ΠΏΠΎΠΏΡΡΠΊΠ΅ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅, ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ Π±ΡΠ΄Π΅Ρ Π·Π°ΠΊΡΡΡΠΎ ΠΏΠΎ ΡΠ°ΠΉΠΌ-Π°ΡΡΡ. Π ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ Reliable UDP ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡΡΡΡ Π΄Π²Π° ΡΠ°ΠΉΠΌΠ΅ΡΠ° Π΄Π»Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ ΡΠ°ΠΉΠΌ-Π°ΡΡΠΎΠ². ΠΠ΅ΡΠ²ΡΠΉ, ΡΠ°Π±ΠΎΡΠΈΠΉ ΡΠ°ΠΉΠΌΠ΅Ρ, ΡΠ»ΡΠΆΠΈΡ Π΄Π»Ρ ΠΎΠΆΠΈΠ΄Π°Π½ΠΈΡ ΠΎΡΠ²Π΅ΡΠ° ΠΎΡ ΡΠ΄Π°Π»Π΅Π½Π½ΠΎΠ³ΠΎ Ρ ΠΎΡΡΠ°. ΠΡΠ»ΠΈ ΠΎΠ½ ΡΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π½Π° ΡΡΠΎΡΠΎΠ½Π΅-ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Π΅, ΡΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΠΏΠΎΠ²ΡΠΎΡΠ½Π°Ρ ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ ΠΎΡΠΏΡΠ°Π²Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠ°. ΠΡΠ»ΠΈ ΠΆΠ΅ ΡΠ°ΠΉΠΌΠ΅Ρ ΡΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Ρ ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ, ΡΠΎ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° ΠΏΠΎΡΠ΅ΡΡΠ½Π½ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ ΠΈ ΠΎΡΠΏΡΠ°Π²Π»ΡΡΡΡΡ Π·Π°ΠΏΡΠΎΡΡ Π½Π° ΠΏΠΎΠ²ΡΠΎΡΠ½ΡΡ Π΄ΠΎΡΡΠ°Π²ΠΊΡ.
ΠΡΠΎΡΠΎΠΉ ΡΠ°ΠΉΠΌΠ΅Ρ β Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌ Π΄Π»Ρ Π·Π°ΠΊΡΡΡΠΈΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π² ΡΠ»ΡΡΠ°Π΅ ΠΎΡΡΡΡΡΡΠ²ΠΈΡ ΡΠ²ΡΠ·ΠΈ ΠΌΠ΅ΠΆΠ΄Ρ ΡΠ·Π»Π°ΠΌΠΈ. ΠΠ»Ρ ΡΡΠΎΡΠΎΠ½Ρ-ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ ΠΎΠ½ Π·Π°ΠΏΡΡΠΊΠ°Π΅ΡΡΡ ΡΡΠ°Π·Ρ ΠΏΠΎΡΠ»Π΅ ΡΡΠ°Π±Π°ΡΡΠ²Π°Π½ΠΈΡ ΡΠ°Π±ΠΎΡΠ΅Π³ΠΎ ΡΠ°ΠΉΠΌΠ΅ΡΠ°, ΠΈ ΠΎΠΆΠΈΠ΄Π°Π΅Ρ ΠΎΡΠ²Π΅ΡΠ° ΠΎΡ ΡΠ΄Π°Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠ·Π»Π°. Π ΡΠ»ΡΡΠ°Π΅ ΠΎΡΡΡΡΡΡΠ²ΠΈΡ ΠΎΡΠ²Π΅ΡΠ° Π·Π° ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½Π½ΡΠΉ ΠΏΠ΅ΡΠΈΠΎΠ΄ β ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ Π·Π°Π²Π΅ΡΡΠ°Π΅ΡΡΡ ΠΈ ΡΠ΅ΡΡΡΡΡ ΠΎΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°ΡΡΡΡ. ΠΠ»Ρ ΡΡΠΎΡΠΎΠ½Ρ-ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ, ΡΠ°ΠΉΠΌΠ΅Ρ Π·Π°ΠΊΡΡΡΠΈΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ Π·Π°ΠΏΡΡΠΊΠ°Π΅ΡΡΡ ΠΏΠΎΡΠ»Π΅ Π΄Π²ΠΎΠΉΠ½ΠΎΠ³ΠΎ ΡΡΠ°Π±Π°ΡΡΠ²Π°Π½ΠΈΡ ΡΠ°Π±ΠΎΡΠ΅Π³ΠΎ ΡΠ°ΠΉΠΌΠ΅ΡΠ°. ΠΡΠΎ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π»Ρ ΡΡΡΠ°Ρ ΠΎΠ²ΠΊΠΈ ΠΎΡ ΠΏΠΎΡΠ΅ΡΠΈ ΠΏΠ°ΠΊΠ΅ΡΠ° ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ. ΠΡΠΈ ΡΡΠ°Π±Π°ΡΡΠ²Π°Π½ΠΈΠΈ ΡΠ°ΠΉΠΌΠ΅ΡΠ°, ΡΠ°ΠΊΠΆΠ΅ Π·Π°Π²Π΅ΡΡΠ°Π΅ΡΡΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΠΈ Π²ΡΡΠ²ΠΎΠ±ΠΎΠΆΠ΄Π°ΡΡΡΡ ΡΠ΅ΡΡΡΡΡ.
ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Reliable UDP
ΠΡΠΈΠ½ΡΠΈΠΏΡ ΡΠ°Π±ΠΎΡΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π° ΡΠ΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π½Ρ Π² ΠΊΠΎΠ½Π΅ΡΠ½ΠΎΠΌ Π°Π²ΡΠΎΠΌΠ°ΡΠ΅, ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΎΡΠ²Π΅ΡΠ°Π΅Ρ Π·Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΡΡ Π»ΠΎΠ³ΠΈΠΊΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ².
ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ Reliable UDP:
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 ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΠ΅Ρ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π΄Π»Ρ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ:
ΠΡΡ Π»ΠΎΠ³ΠΈΠΊΡ ΡΠ°Π±ΠΎΡΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π° ΡΠ΅Π°Π»ΠΈΠ·ΡΡΡ ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»Π΅Π½Π½ΡΠ΅ Π²ΡΡΠ΅ ΠΊΠ»Π°ΡΡΡ, ΡΠΎΠ²ΠΌΠ΅ΡΡΠ½ΠΎ ΡΠΎ Π²ΡΠΏΠΎΠΌΠΎΠ³Π°ΡΠ΅Π»ΡΠ½ΡΠΌ ΠΊΠ»Π°ΡΡΠΎΠΌ, ΠΏΡΠ΅Π΄ΠΎΡΡΠ°Π²Π»ΡΡΡΠΈΠΌ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ, ΡΠ°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΠΎΡΡΡΠΎΠ΅Π½ΠΈΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° 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 );
}
}
ΠΠ»ΡΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. Π‘ΠΎΠ·Π΄Π°Π½ΠΈΠ΅ ΠΈ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠΉ
Π’Π΅ΠΏΠ΅ΡΡ, ΠΊΠΎΠ³Π΄Π° ΠΌΡ ΠΏΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΠ»ΠΈΡΡ Ρ ΠΎΡΠ½ΠΎΠ²Π½ΡΠΌΠΈ ΡΠΎΡΡΠΎΡΠ½ΠΈΡΠΌΠΈ ΠΈ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌΠΈ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΠΌΠΈ Π΄Π»Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΠΎΡΡΠΎΡΠ½ΠΈΠΉ, ΠΌΠΎΠΆΠ½ΠΎ ΡΠ°Π·ΠΎΠ±ΡΠ°ΡΡ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈΠΌΠ΅ΡΠΎΠ² ΡΠ°Π±ΠΎΡΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π°.
ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π΄Π°Π½Π½ΡΡ
Π² Π½ΠΎΡΠΌΠ°Π»ΡΠ½ΡΡ
ΡΡΠ»ΠΎΠ²ΠΈΡΡ
:
Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎ ΡΠΎΠ·Π΄Π°Π½ΠΈΠ΅ 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. Π Π°ΡΡΠΌΠΎΡΡΠΈΠΌ ΠΏΡΠΈΠΌΠ΅Ρ, Π² ΠΊΠΎΡΠΎΡΠΎΠΌ Π½Π° ΠΏΡΠΎΠΌΠ΅ΠΆΡΡΠΎΡΠ½ΡΠΌ ΡΠ·Π»Π΅ ΠΏΡΠΎΠΈΠ·ΠΎΡΠ΅Π» ΡΠ±ΠΎΠΉ ΠΈ Π΄ΠΎΡΡΠ°Π²ΠΊΠ° Π΄Π°Π½Π½ΡΡ
Π² ΠΎΠ±ΠΎΠΈΡ
Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΡΡΠ°Π»Π° Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ.
ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° Π·Π°ΠΊΡΡΡΠΈΡ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΠΏΠΎ ΡΠ°ΠΉΠΌΡ-Π°ΡΡΡ:
ΠΠ°ΠΊ Π²ΠΈΠ΄Π½ΠΎ ΠΈΠ· Π΄ΠΈΠ°Π³ΡΠ°ΠΌΠΌΡ, ΡΠ°Π±ΠΎΡΠΈΠΉ ΡΠ°ΠΉΠΌΠ΅Ρ Ρ ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ Π²ΠΊΠ»ΡΡΠ°Π΅ΡΡΡ ΡΡΠ°Π·Ρ ΠΏΠΎΡΠ»Π΅ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ Π±Π»ΠΎΠΊΠ° ΠΏΠ°ΠΊΠ΅ΡΠΎΠ². ΠΡΠΎ ΠΏΡΠΎΠΈΡΡ
ΠΎΠ΄ΠΈΡ Π² ΠΌΠ΅ΡΠΎΠ΄Π΅ 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);
}
}
ΠΠ»ΡΠ±ΠΆΠ΅ Π² ΠΊΠΎΠ΄. ΠΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π΄Π°Π½Π½ΡΡ
ΠΠΈΠ°Π³ΡΠ°ΠΌΠΌΠ° Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ Π΄Π°Π½Π½ΡΡ
ΠΏΡΠΈ ΠΏΠΎΡΠ΅ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΠ°:
ΠΠ°ΠΊ ΡΠΆΠ΅ ΠΎΠ±ΡΡΠΆΠ΄Π°Π»ΠΎΡΡ Π² Π·Π°ΠΊΡΡΡΠΈΠΈ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ ΠΏΠΎ ΡΠ°ΠΉΠΌ-Π°ΡΡΡ, ΠΏΠΎ ΠΈΡΡΠ΅ΡΠ΅Π½ΠΈΡ ΡΠ°Π±ΠΎΡΠ΅Π³ΠΎ ΡΠ°ΠΉΠΌΠ΅ΡΠ° Ρ ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ ΠΏΡΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π½Π° ΠΏΠΎΡΠ΅ΡΡΠ½Π½ΡΠ΅ ΠΏΠ°ΠΊΠ΅ΡΡ. Π ΡΠ»ΡΡΠ°Π΅ Π½Π°Π»ΠΈΡΠΈΡ ΠΏΠΎΡΠ΅ΡΡ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² Π±ΡΠ΄Π΅Ρ ΡΠΎΡΡΠ°Π²Π»Π΅Π½ ΡΠΏΠΈΡΠΎΠΊ Π½ΠΎΠΌΠ΅Ρ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ², Π½Π΅ Π΄ΠΎΡΠ΅Π΄ΡΠΈΡ
Π΄ΠΎ ΠΏΠΎΠ»ΡΡΠ°ΡΠ΅Π»Ρ. ΠΠ°Π½Π½ΡΠ΅ Π½ΠΎΠΌΠ΅ΡΠ° Π·Π°Π½ΠΎΡΡΡΡΡ Π² ΠΌΠ°ΡΡΠΈΠ² 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:
ΠΠΎΠ»Π΅Π·Π½ΡΠ΅ ΡΡΡΠ»ΠΊΠΈ ΠΈ ΡΡΠ°ΡΡΠΈ
- Π‘ΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π° TCP:
Π½Π° Π°Π½Π³Π»ΠΈΠΉΡΠΊΠΎΠΌ ΠΈΠ½Π° ΡΡΡΡΠΊΠΎΠΌ - Π‘ΠΏΠ΅ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π° UDP:
Π½Π° Π°Π½Π³Π»ΠΈΠΉΡΠΊΠΎΠΌ ΠΈΠ½Π° ΡΡΡΡΠΊΠΎΠΌ - ΠΠ±ΡΡΠΆΠ΄Π΅Π½ΠΈΠ΅ RUDP ΠΏΡΠΎΡΠΎΠΊΠΎΠ»Π°:
draft-ietf-sigtran-reliable-udp-00 - Reliable Data Protocol:
rfc 908 ΠΈrfc 1151 - ΠΡΠΎΡΡΠ°Ρ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ Π΄ΠΎΡΡΠ°Π²ΠΊΠΈ ΠΏΠΎ UDP:
Take Total Control Of Your Networking With .NET And UDP - Π‘ΡΠ°ΡΡΡ, ΠΎΠΏΠΈΡΡΠ²Π°ΡΡΠ°Ρ ΠΌΠ΅Ρ
Π°Π½ΠΈΠ·ΠΌΡ ΠΏΡΠ΅ΠΎΠ΄ΠΎΠ»Π΅Π½ΠΈΡ NAT’ΠΎΠ²:
Peer-to-Peer Communication Across Network Address Translators - Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΠΎΠΉ ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ:
Implementing the CLR Asynchronous Programming Model ΠΈHow to implement the IAsyncResult design pattern - ΠΠ΅ΡΠ΅Π½ΠΎΡ Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΠΎΠΉ ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ Π² Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΡΠΉ ΡΠ°Π±Π»ΠΎΠ½, ΠΎΡΠ½ΠΎΠ²Π°Π½Π½ΡΠΉ Π½Π° Π·Π°Π΄Π°ΡΠ°Ρ
(APM Π² TAP):
TPL and Traditional .NET Asynchronous Programming
Interop with Other Asynchronous Patterns and Types
Update: Π‘ΠΏΠ°ΡΠΈΠ±ΠΎ
ΠΡΡΠΎΡΠ½ΠΈΠΊ: habr.com