แแแขแแ แแแขแ แแแแ แฎแแแก แฌแแ แจแแแชแแแแ. แแแขแแ แแแขแแก แแ แ-แแ แแ แแแแแแ แ แแ แแขแแแแแ - UDP แแแแแแงแแแแแ แแแแแแแชแแแแแก แแแแ แแ แ แแฎแแแแ แแแขแแแ แแแแแแก แแ แแแฃแฌแงแแแแแแแก แแแฌแแแแแแกแแแแก, แแ แแแแ แฅแกแแแแก แแแแแซแแแก แจแแ แแก "แแแแฎแแแแแแแ" แแแแจแแ แแแแก แฃแแ แฃแแแแแกแแงแแคแแ. แแแ แขแแแ แแแแแแแแก แแแแ, แแ แแ แแขแแแแแก แแฅแแก แแ แแแแแ แแแ แ แแแฃแแแแแแแ แแแแแงแแแแแ, แแฃแแชแ แแ แแขแแแแแแก แแแแแแแแแแแแแ, แ แแแแ แแชแแ แแแ แแแขแแ แแแฃแแ แแแฌแแแแแแก แแ แแ แกแแแแแ, แแ แกแแ แแแแฅแ แแแ. แแก แกแขแแขแแ แแฆแฌแแ แก แแแ แแแขแแ แแแฃแแ แแแฌแแแแแแก แแ แแขแแแแแแก แแแแฎแแ แชแแแแแแแก UDP-แแ.
แจแแแแแ แกแ:
DisposeByTimeout แแแแแแ ProcessPackets แแแแแแ ReceivePacket แแแแแแ แแแแแขแแก แแแแแแแแแก แแแแแแ
Entry
แแแขแแ แแแขแแก แแแแแแแแ แแแแ แแ แฅแแขแแฅแขแฃแ แ แแแแแแแกแฌแแแแแแ แแแกแแแแ แแแแแก แแ แแแแแ แแแแ แกแแแ แชแแก, แ แแแแแจแแช แแแแแแฃแ แแแแแซแก แฐแฅแแแแ แแแแแแแฃแ แ แแ แฃแแแแแแฃแ แ IP แแแกแแแแ แแ แแ แจแแแซแแ แแแ แแแแแ แแแฃแแแแจแแ แแแก แกแฎแแ แแแแแซแแแก. แแฎแแ แแแขแแ แแแขแก, แคแแฅแขแแแ แแแแ, แแฅแแก แแแแกแฎแแแแแแฃแแ แแ แฅแแขแแฅแขแฃแ แ - แแแแแแแฃแ แ IP แแแกแแแแ แแแแแก แแ แแ แแ แ แแ แแ แแแแแ แฃแแแแ, แกแแแแช แแแ แแแ แแแกแแแแ แแแแ แแแแแแแ NAT แแแฌแงแแแแแแแแแแก แแแฆแแ.
แแแขแแ แแแขแแก แแก แแ แฅแแขแแฅแขแฃแ แ แกแแแแแ แแกแแ แกแฌแแ แแ แแแแแแข-แกแแ แแแ แแก แแแแฃแแแแแชแแแกแแแแก, แกแแแแช แแแแแแขแแแ แจแแแซแแแแ แแงแแแแ แแแ แซแ แฅแกแแแแแจแ, แฎแแแ แกแแ แแแ แแแก แแฅแแ แแแแแแแฃแ แ แแแกแแแแ แแ. แแแแ แแ แแก แฅแแแแก แกแแ แแฃแแแแแก แแ แ แแแแแซแแก แแแ แแแแแ แ แแแแจแแ แแกแแแแก แกแฎแแแแแกแฎแแ แแแ แซแ แฅแกแแแแแ. แแแ แแแแแ แ แแแแจแแ แ แแ แแแแแซแก แจแแ แแก แแแแจแแแแแแแแแแ peer-to-peer แแแแแแแชแแแแแกแแแแก, แ แแแแ แแชแแ แฎแแแก แแแแแชแแแ (Skype), แแแแแแฃแขแแ แแ แแแกแขแแแชแแฃแ แ แฌแแแแแแก แแแแแแแแ (TeamViewer) แแ แแแแแแ แแแแแจแแแ.
แแ แ-แแ แ แงแแแแแแ แแคแแฅแขแฃแ แแแแแแก แกแฎแแแแแกแฎแแ แแแ แซแ แฅแกแแแจแ แแแฌแงแแแแ แแแฌแงแแแแแแแแแก แจแแ แแก แแแแแขแแแแแแแ แแแแจแแ แแก แแแแงแแ แแแแก แแแแแแ, แฎแแ แแแแก แแแ แขแงแแ แแฌแแแแแ. แแก แขแแฅแแแแ แงแแแแแแ แฎแจแแ แแ แแแแแแงแแแแแ UDP แแ แแขแแแแแแ แแแคแฃแซแแแแฃแ แแแแแแแชแแแแแแ.
แแแแ แแ แแฃ แแฅแแแแก แแแแแแแชแแแก แกแญแแ แแแแ แแแแแชแแแแ แแแ แแแขแแ แแแฃแแ แแแฌแแแแแ, แแแแแแแแแ, แแฅแแแ แแแแแ แแชแฎแแแ แคแแแแแแก แแแแแแฃแขแแ แแแก แจแแ แแก, แแแจแแ UDP-แก แแแแแงแแแแแแก แแแแ แ แกแแ แแฃแแ แแฅแแแแ แแแแก แแแแ, แ แแ UDP แแ แแ แแก แแแ แแแขแแ แแแฃแแ แแแฌแแแแแแก แแ แแขแแแแแ แแ แแ แฃแแ แฃแแแแแงแแคแก แแแแแขแแก แแแฌแแแแแแก แฌแแกแ แแแจแ, แแแแกแฎแแแแแแแ TCP-แแกแแแ. แแฅแแ.
แแ แจแแแแฎแแแแแจแ, แแแแแขแแก แแแ แแแขแแ แแแฃแแ แแแฌแแแแแแก แฃแแ แฃแแแแแกแแงแแคแแ, แกแแญแแ แแ แแแแแแแชแแแก แคแแแแก แแ แแขแแแแแแก แแแแแ แแแ, แ แแแแแแช แฃแแ แฃแแแแแงแแคแก แแฃแชแแแแแแ แคแฃแแฅแชแแแแแ แแแแก แแ แแฃแจแแแแก UDP-แแ.
แแกแฃแ แก แแแฃแงแแแแแแแแ แแฆแแแแจแแ, แ แแ แแ แกแแแแแก TCP แฎแแ แแแแแแก แขแแฅแแแแ แกแฎแแแแแกแฎแแ แแแ แซแ แฅแกแแแจแ แแแแแซแแแก แจแแ แแก TCP แแแแจแแ แแแแก แแแกแแแงแแ แแแแแ, แแแแ แแ แแ แแแแแ NAT แแแฌแงแแแแแแแแก แแแแ แแแกแ แแฎแแ แแแญแแ แแก แแ แแ แกแแแแแแก แแแแ, แแก แฉแแแฃแแแแ แแ แแ แแแแแฎแแแแแ, แ แแแแ แช แแแแแแจแแ แแแแก แแแแแแ แ แแแ. แแกแแแ แแแแแซแแแ.
แแ แกแขแแขแแแก แแแ แฉแแแแแ แแแฌแแแแกแแแแก แแ แแฎแแแแ แแแ แแแขแแ แแแฃแแ แแแฌแแแแแแก แแ แแขแแแแแแก แแแแฎแแ แชแแแแแแแแ แแแแแแแฎแแแแแ แงแฃแ แแแฆแแแแก. UDP แฎแแ แแแแแแก แขแแฅแแแแแก แแแแฎแแ แชแแแแแแ แแฆแฌแแ แแแ แแฅแแแแ แจแแแแแ แกแขแแขแแแแจแ.
แแ แแขแแแแแแก แแแแฎแแแแแแ
- แกแแแแ แแแแแขแแก แแแฌแแแแแ, แ แแแแแแช แแแแฎแแ แชแแแแแแฃแแแ แแแแแแแแ แแแแแฎแแแฃแ แแแแก แแแฅแแแแแแแ (แ.แฌ. แแแแแขแแฃแ แ แแฆแแแ แแแ)
- แแแแ แแแแแชแแแแแแก แแคแแฅแขแฃแ แ แแแแแชแแแแก แกแแญแแ แแแแ, แ.แ. แแ แแขแแแแแแ แแแแแแแ แฃแแแ แแแชแแแแก แแ แแกแแญแแ แ แแแแแขแแก แ แแแแแแ
- แจแแกแแซแแแแแแ แฃแแแ แแงแแก แแแฌแแแแแแก แแแแแกแขแฃแ แแแแก แแแฅแแแแแแแก แแแฃแฅแแแแ ("แกแฃแคแแ" UDP แแ แแขแแแแแแก แคแฃแแฅแชแแแแแ แแแแก แจแแกแแซแแแแแแแ)
- แแ แซแแแแแแก แ แแแแแแก แแแแฎแแ แชแแแแแแแก แจแแกแแซแแแแแแแ, แแแแแแฃแแ แจแแขแงแแแแแแแแก แแแแแกแขแฃแ แแแแ
- แแ แแขแแแแแแ แแแแแชแแแแ แแแแแชแแแแก แซแแ แแแแแ แแ แแแฃแแ แฃแแแ แแงแแก แจแแขแงแแแแแแแ
แแก แแแแฎแแแแแแ แแแแฌแแแแ แแแแฎแแแแ แกแแแแ แแแแแชแแแแ แแ แแขแแแแแแก แแแแฎแแแแแแก, แ แแแแแแแช แแฆแฌแแ แแแแ
แแ แแแแฎแแแแแแแก แแแกแแแแแแ, แแแแแ แจแแแฎแแแแ แแแแแชแแแแ แแแแแชแแแแก แแแแแแก แแ แฅแกแแแฃแ แแแแแซแก แจแแ แแก TCP แแ UDP แแ แแขแแแแแแแแก แแแแแงแแแแแแ. แแแแแ แแ แแแ แจแแแแฎแแแแแจแ แแแแแแแ แแแแก แแ แแ แแแแแขแ.
แแ แแแแขแแ แแฅแขแแฃแแ แแแแแชแแแแแแก แแแแแชแแแ TCP-แแ:
แ แแแแ แช แกแฅแแแแแแ แฎแแแแแ, แแแแแขแแก แแแแแ แแแแก แจแแแแฎแแแแแจแ, TCP แแฆแแแแฉแแแก แแแแแ แแฃแ แแแแแขแก แแ แแชแแแแแแก แแแก แแแแแแแแแแแก แแแแแ แแฃแแ แกแแแแแแขแแก แแแแ แแก แแแแฎแแแแแ.
แแแแแชแแแแ แแแแแชแแแ UDP แแ แแขแแแแแแ:
UDP แแ แแฆแแแก แแแ แแแแก แแแแแแแแแแก แแแแแฏแแแก. UDP แแ แแขแแแแแจแ แแแแแชแแแแก แจแแชแแแแแแแก แแแแขแ แแแ แแแแแแแแ แแแแแแแชแแแก แแแกแฃแฎแแกแแแแแแแแแ.
TCP แแ แแขแแแแแจแ แจแแชแแแแแก แแแแแแแแแ แแแแฆแฌแแแ แแแแ แแแแแซแแแ แแแแจแแ แแก แแแแงแแ แแแแ, แแ แแแแจแแ แแก แแแแแแแ แแแแแก แจแแแแฎแแแ, แแแแแแฃแ แแแแแขแแก แกแแแแฃแ แจแ แแแแแแแแแแ แแแแขแแแแก แ แแแแแแแแแก แแแแแแแแแ แแ แฅแแแแ แแแแก แจแแขแงแแแแแแแแ แแแแแกแขแฃแ แแแแก แแแแ แแก แแแแแงแแแแแแ.
แแแ แแ แแแแกแ, แจแแกแ แฃแแแแแก แแแกแแฃแแฏแแแแกแแแแแ (แแแฃ แแ แแแ แแแขแ แกแแแแแแขแแก แแแแแแแแ แแแแแกแขแฃแ แแแแก แแแฆแแแแก แแแ แแจแ), TCP แแ แแขแแแแแ แแงแแแแแก แแแ แแ แฌแแแแแฃแ แแแแแชแแแแก แคแแแฏแแ แแก - แแแแแชแแแแ แแแแขแแแแก แ แแแแแแแแแก, แ แแแแแกแแช แกแแแแแแขแแก แแแแแแแแแ แแแแแแก.
แแแแแขแแแแแ แแแคแแ แแแชแแแกแแแแก TCP แแ แแขแแแแแแก แจแแกแแฎแแ แแฎ
แแแแแแฆแแแจแแฃแแแแแ แแ แแแแแ, แ แแ UDP-แแ แจแแขแงแแแแแแแแก แแแฌแแแแแแก แกแแแแแแ แแ แแขแแแแแแก แจแแกแแฅแแแแแแ (แจแแแแแแแจแ แกแแแแ UDP), แกแแญแแ แแ TCP-แแก แแกแแแแกแ แแแแแชแแแแ แแแแแชแแแแก แแแฅแแแแแแแแแก แแแแแ แแแ. แแแ แซแแ:
- แแแแจแแ แแก แแแแแแแ แแแแแก แจแแแแฎแแ
- แแแแแแงแแแแ แกแแแแแแขแแก แแฃแแแ แแชแแ
- แแแแแแงแแแแ แกแแแชแแแแฃแ แ แแแแแกแขแฃแ แแแแก แแแแแขแแแ
- แแแแแแงแแแแ แแแแแ แขแแแแแฃแแ แคแแแฏแ แแก แแแฅแแแแแแ แแ แแขแแแแแแก แแแแขแแ แฃแแแ แแแแแแแก แแแกแแแ แแแแแ
แแแ แแ แแแแกแ, แแญแแ แแแแแ:
- แจแแขแงแแแแแแแแก แแแฌแงแแแแก แกแแแแแแ, แ แแแ แแแแแงแแก แ แแกแฃแ แกแแแ แแแแจแแ แแกแแแแก
- แแแแแแแแแ แจแแขแงแแแแแแแแก แแแกแแกแ แฃแแแก แกแแแแแแ, แแแแแกแชแแก แแแฆแแแฃแแ แจแแขแงแแแแแแแ แแแแแ แแแแแแแก แแแแแแแชแแแจแ แแ แแแแแแแแกแฃแคแแแก แแ แแขแแแแแแก แ แแกแฃแ แกแแแ
- แแแแ แแแแชแแ แแแแจแแ แแก แกแแแชแแคแแแฃแ แแ แแขแแแแแก แแแแแ แแแก แแแฌแแแแแแก แแแแแกแขแฃแ แแแแก แแแฅแแแแแแ "แกแฃแคแแ" UDP-แแก แกแแฎแแ
แกแแแแ UDP แกแแแแฃแ แ
แจแแแแฎแกแแแแแ, แ แแ UDP แแแขแแแ แแแ แฉแแกแแฃแแแ IP แแแขแแแ แแแแจแ. แกแแแแ UDP แแแแแขแ แกแแแแแแแแ "แจแแคแฃแแฃแแแ" UDP แแแขแแแ แแแแจแ.
แกแแแแแแ UDP แกแแแแฃแ แแก แแแแแแกแฃแแแชแแ:
แกแแแแแแ UDP แกแแแแฃแ แแก แกแขแ แฃแฅแขแฃแ แ แกแแแแแแ แแแ แขแแแแ:
- แแ แแจแแแ - แแแแแขแแก แแแแขแ แแแแก แแ แแจแแแ
- MessageType - แจแแขแงแแแแแแแแแแก แขแแแ, แ แแแแแกแแช แแงแแแแแแ แแแแ แแแแแแแก แแแแแแแชแแแแ แแแแแ แแขแฃแแ แจแแขแงแแแแแแแแแแก แแแแแกแแฌแแ แแ
- TransmissionId - แแแแแชแแแแก แแแแแ แ, แแแแฆแแแแก แแแกแแแแ แแแแ แแ แแแ แขแแแ แแ แแแ, แชแแแกแแฎแแ แแแแกแแแฆแแ แแแก แแแแจแแ แก
- PacketNumber - แแแแแขแแก แแแแแ แ
- แแคแชแแแแ - แแแแแขแแแแแ แแ แแขแแแแแแก แแแ แแแแขแ แแแ. แแแ แแแแ แแแแแขแแก แจแแแแฎแแแแแจแ, แแแ แแแแแแงแแแแแ แจแแขแงแแแแแแแแก แแแแแก แแแแแแแแแกแแแแก
แแ แแจแแแ แแกแแแแ:
- FirstPacket - แจแแขแงแแแแแแแแก แแแ แแแแ แแแแแขแ
- NoAsk - แจแแขแงแแแแแแแ แแ แกแแญแแ แแแแก แแแแแกแขแฃแ แแแแก แแแฅแแแแแแแก แฉแแ แแแแก
- LastPacket - แจแแขแงแแแแแแแแก แแแแ แแแแแขแ
- RequestForPacket - แแแแแกแขแฃแ แแแแก แแแแแขแ แแ แแแแแ แแฃแแ แแแแแขแแก แแแแฎแแแแ
แแ แแขแแแแแแก แแแแแแ แแ แแแชแแแแแ
แแแแแแแแ แกแแแแ UDP แแ แแแแขแแ แแแฃแแแ แแ แแแแแซแก แจแแ แแก แจแแขแงแแแแแแแแก แแแ แแแขแแ แแแฃแ แแแแแชแแแแแ, แแแก แฃแแแ แจแแแซแแแก แแแแจแแ แแก แแแแงแแ แแแ แแแแ แ แแฎแแ แแกแแแ. แแแแจแแ แแก แแแกแแแงแแ แแแแแ, แแแแแแแแแ แแแแแแแแก แแแแแขแก FirstPacket แแ แแจแแ, แ แแแแแแแช แแแกแฃแฎแ แแแจแแแแก แแแแจแแ แแก แแแแงแแ แแแแก. แงแแแแ แกแแแแกแฃแฎแ แแแแแขแ, แแ แกแฎแแ แกแแขแงแแแแแ แ แแ แแแฅแแแ, แแแแแกแขแฃแ แแแแก แแแแแขแแแ, แงแแแแแแแแก แแแแแแก PacketNumber แแแแแก แแแแจแแแแแแแแก แแ แแแ แแแขแ, แแแแ แ แฌแแ แแแขแแแแ แแแฆแแแฃแแ แแแแแขแแแแก แฃแแแแแกแ PacketNumber แแแแจแแแแแแแ. แแคแชแแแแแก แแแแ แแแ แแแแ แแแแแแแแแแ แแแแแขแแกแแแแก แแ แแก แจแแขแงแแแแแแแแก แแแแ.
แแกแแแแกแ แแแฅแแแแแแ แแแแแแงแแแแแ แแแแจแแ แแก แจแแกแแฌแงแแแขแแ. LastPacket แแ แแจแ แแแงแแแแแฃแแแ แจแแขแงแแแแแแแแก แแแแ แแแแแขแแ. แกแแแแกแฃแฎแ แแแแแขแจแ แแแแแแแแฃแแแ แแแแ แแแแแขแแก แแแแแ แ + 1, แ แแช แแแแฆแแแ แแฎแแ แแกแแแแก แแแจแแแแก แจแแขแงแแแแแแแแก แฌแแ แแแขแแแฃแ แแแฌแแแแแแก.
แแแแจแแ แแก แแแแงแแ แแแแกแ แแ แจแแฌแงแแแขแแก แแแแแ แแแ:
แ แแแแกแแช แแแแจแแ แ แแแแงแแ แแแแ, แแแแแชแแแแ แแแแแชแแแ แแฌแงแแแ. แแแแแชแแแแแ แแแแแแชแแแ แแแแแขแแแแก แแแแแแแจแ. แแแแแแฃแแ แแแแแ, แแแ แแ แฃแแแแแกแแแแแแกแ, แจแแแชแแแก แแแแแขแแแแก แคแแฅแกแแ แแแฃแ แ แแแแแแแแแก. แแก แฃแแ แแก แแแฆแแแแก/แแแแแชแแแแก แคแแแฏแ แแก แแแแแก. แแแแแชแแแแ แแแแ แแแแแก แจแแแซแแแแ แฐแฅแแแแแก แแแแแแแ แแแแแขแแแ. แแแแแแฃแแ แแแแแแก แแแแแแแแแก แจแแแแแ, แแแแแแแแ แแฎแแ แ แแแแแแแ แแแฌแแแแแแก แแแแแกแขแฃแ แแแแก แแ แแแแฎแแแแแก แแแแแ แแฃแแ แแแแแขแแแแก แฎแแแแฎแแ แแแฌแแแแแแก แจแแกแแฎแแ, แขแแแแแก แแแฆแแแแก/แแแแแชแแแแก แคแแแฏแแ แแก แฆแแ แแแกแฃแฎแแแแก แแแกแแฆแแแแ. แแแแแแก แแแฌแแแแแแก แแแแแกแขแฃแ แแแแก แแแฆแแแแก แจแแแแแ, แแแฆแแแแก/แแแแแชแแแแก แคแแแฏแแ แ แแชแแแแแ แแ แแแแแแแแแ แแแแแชแแแแ แจแแแแแแ แแแแแ.
แแแแฆแแแ แแฎแแ แ แแฆแแแก แแแแแขแแแก. แแแแแแฃแแ แแแแแขแ แแแฌแแแแแ, แ แแแ แแแฎแแ, แแแฎแแแแแ แแฃ แแ แ แแแแแชแแแแก แคแแแฏแแ แแจแ. แแแแแขแแแ แแ แแฃแแแแแแขแแแ, แ แแแแแแแช แแ แแแฎแแแแแ แคแแแฏแแ แแจแ, แแคแแแขแ แแแ. แแแแขแแ แ แแ แแฃ แคแแแฏแ แแก แแแแ แคแแฅแกแแ แแแแ แแ แแแแแแ แแแแฆแแแแกแแแแก แแ แแแแแแแแแแกแแแแก, แแแจแแ แแแแแขแแแแก แแแแแแก แแแแแ แแแแก แแแ แแจแ แแแฌแแแแแแก แจแแแแฎแแแแแจแ, แคแแแฏแแ แ แแแแแแแก แแแแแชแแแแ แจแแแแแแ แแแแแแก แแแแแขแแแแก แแแกแแฆแแแแ แแ แแแฌแแแแแแก แแแแแกแขแฃแ แแแ แฎแแแแ. แแแแแแแแแแ. แแฃ แคแแแฏแแ แ แแ แแแกแแแ แกแแแฃแจแแ แขแแแแแ แแก แแแแ แแแแแแแแ แแแแแจแ, แแแจแแ แแแแฌแงแแแ แจแแแแฌแแแแ, แ แแแแแแแแแแช แแ แแฅแแ แแแฌแแแแแฃแแ แแแแแขแแแ แแ แแแแแแแแแแแ แแแแฎแแแแ แฎแแแแฎแแ แแแฌแแแแแแแ.
แฎแแแแฎแแแ แแแแแชแแแแก แแแแแ แแแ:
แแแแแแ แแ แแ แแขแแแแแแก แขแแแแแ แ
แแแแจแแ แแก แแแแงแแ แแแแก แ แแแแแแแแ แแแแแแ แแ แกแแแแแก. แแแแแแแแแ, แแฃ แแแแฆแแแ แแฎแแ แ แฎแแแแแ แแจแแ. แแ แจแแแแฎแแแแแจแ, แแแแจแแ แแก แแแแงแแ แแแแก แแชแแแแแแแกแแก, แแแแจแแ แ แแแแฎแฃแ แแแ แแ แแแก แแแแฌแฃแ แแแก แแแแ. แกแแแแ UDP แแแแแ แแแ แแงแแแแแก แแ แขแแแแแ แก แแ แแแก แแแแฌแฃแ แแแก แแแกแแงแแแแแแแ. แแแ แแแแ, แกแแแฃแจแแ แขแแแแแ แ, แแแแแแงแแแแแ แแแกแขแแแชแแฃแ แ แแแกแแแแซแแแก แแแกแฃแฎแแก แแแแแแแแจแ. แแฃ แแก แแจแแแแ แแแแแแแแแแก แแฎแแ แแก, แแแจแแ แแแแ แแแแแแแแแแ แแแแแขแ แฎแแแแฎแแ แแแแแแแแแ. แแฃ แขแแแแแ แ แแฌแฃแ แแแ แแแแฆแแแแ, แแแจแแ แฎแแแแ แแแแแ แแฃแแ แแแแแขแแแแก แจแแแแฌแแแแ แแ แแแแแแแแแ แแแแฎแแแแ แฎแแแแฎแแ แแแฌแแแแแแก แจแแกแแฎแแ.
แแแแ แ แขแแแแแ แ แกแแญแแ แแ แแแแจแแ แแก แแแฎแฃแ แแแกแแก แแแแแซแแแก แจแแ แแก แแแแฃแแแแแชแแแก แแแแแแแแแแก แจแแแแฎแแแแแจแ. แแแแแแแแแแก แแฎแ แแแแ, แแก แแฌแงแแแ แกแแแฃแจแแ แขแแแแแ แแก แแแแแก แแแแฌแฃแ แแแกแแแแแแ แแ แแแแแแแ แแแกแฃแฎแก แแแกแขแแแชแแฃแ แ แแแแแซแแแแ. แแฃ แแแกแฃแฎแ แแ แแฅแแแแ แแแแแแแแฃแ แแแแแจแ, แแแแจแแ แ แฌแงแแแแ แแ แ แแกแฃแ แกแแแ แแฎแกแแแแ. แแแแฆแแแ แแฎแแ แแกแแแแก, แแแแจแแ แแก แแแฎแฃแ แแแก แขแแแแแ แ แแฌแงแแแ แกแแแฃแจแแ แขแแแแแ แแก แแ แฏแแ แแแแฌแฃแ แแแก แจแแแแแ. แแก แแฃแชแแแแแแแแ แแแแแกแขแฃแ แแแแก แแแแแขแแก แแแแแ แแแแก แแแแแแแ แแกแแชแแแแแแแ. แ แแแแกแแช แขแแแแแ แ แแแแแฌแฃแ แแแ, แแแแจแแ แ แแกแแแ แฌแงแแแแ แแ แ แแกแฃแ แกแแแ แแฎแกแแแแ.
แกแแแแแแ UDP แแแแแชแแแแก แแแแแแแ แแแแแก แแแแแ แแแ
แแ แแขแแแแแแก แแ แแแชแแแแแ แแแแแ แแแแแ แกแแกแ แฃแแ แแแแแแแ แแแแแก แแแแฅแแแแจแ, แ แแแแแก แแแแแแฃแแ แแแแแแแ แแแแ แแแกแฃแฎแแกแแแแแแแแ แแแแแขแแก แแแแฃแจแแแแแแก แแแ แแแแฃแ แแแแแแแแ.
แกแแแแ UDP แแแแแแแ แแแแแก แแแแแ แแแ:
แแแฎแฃแ แแแก - แแก แแแแแแแแแ แแ แแ แแก แกแแฎแแแแฌแแคแ, แแก แแ แแก แกแแฌแงแแกแ แแ แแแกแแกแ แฃแแ แฌแแ แขแแแ แแแขแแแแขแแกแแแแก. แกแแฎแแแแฌแแคแแกแแแแก แแแฎแฃแ แแแก แแแแฆแแแ แแแแแชแแแแก แแแแขแ แแแแก แแแแแ, แ แแแแแแช แแกแแแฅแ แแแฃแแ UDP แกแแ แแแ แแก แแแแแ แแแแ, แแแแแขแแแก แแแแแกแชแแแก แจแแกแแแแแแก แแแแจแแ แแแก แแ แแฌแงแแแก แแแแแแแ แแแแแก แแแแฃแจแแแแแแก.
FirstPacketSending โ แกแแฌแงแแกแ แแแแแแแ แแแแ, แ แแแแแจแแช แแ แแก แแแแแแแแ แแแแจแแ แ แจแแขแงแแแแแแแแก แแแแแแแแแกแแก.
แแ แแแแแแแ แแแแแจแ แแแแแแแแแ แแแ แแแแ แแแแแขแ แแแ แแแแฃแ แ แจแแขแงแแแแแแแแแแกแแแแก. แจแแขแงแแแแแแแแแแกแแแแก แแแแแแแแแก แแแแแกแขแฃแ แแแแก แแแ แแจแ, แแก แแ แแก แแ แแแแแ แแ แแแแแแแ แแแแ, แกแแแแช แแแแแแแแแ แแแแแ แจแแขแงแแแแแแแ.
แแแแแแแแแก แชแแแแ โ แซแแ แแแแแ แแแแแแแ แแแแ แจแแขแงแแแแแแแแแแก แแแแแขแแแแก แแแแแชแแแแกแแแแก.
แแแกแแ แแแแแกแแแ แกแแฎแแแแฌแแคแแแแ FirstPacketSending แจแแกแ แฃแแแแฃแแแ แจแแขแงแแแแแแแแก แแแ แแแแ แแแแแขแแก แแแแแแแแแก แจแแแแแ. แกแฌแแ แแ แแ แแแแแแแ แแแแแจแ แแแแแก แงแแแแ แแฆแแแ แแแ แแ แแแแฎแแแแ แฎแแแแฎแแแ แแแแแชแแแแก แจแแกแแฎแแ. แแแกแแแ แแแกแแแ แจแแกแแซแแแแแแแ แแ แจแแแแฎแแแแแจแ - แจแแขแงแแแแแแแแก แฌแแ แแแขแแแฃแแแ แแแฌแแแแแแก แจแแแแฎแแแแแจแ แแ แขแแแแแฃแขแแ.
FirstPacketReceived โ แกแแฌแงแแกแ แแแแแแแ แแแแ แจแแขแงแแแแแแแแก แแแแฆแแแแกแแแแก.
แแก แแแแฌแแแแก แแแแแชแแแแก แแแกแแฌแงแแกแแก แกแแกแฌแแ แแก, แฅแแแแก แกแแญแแ แ แกแขแ แฃแฅแขแฃแ แแแก แแ แแแแแแแแก แแแ แแแแ แแแแแขแแก แแแฆแแแแก แแแแแกแขแฃแ แแแแก.
แจแแขแงแแแแแแแแกแแแแก, แ แแแแแแช แจแแแแแแ แแ แแ แแแแแขแแกแแแ แแ แแแแแแแแแ แแแฌแแแแแแก แแขแแแชแแแฃแแแแแก แแแ แแจแ, แแก แแ แแแแแ แแ แแแแแแแ แแแแแ. แแกแแแ แจแแขแงแแแแแแแแก แแแแฃแจแแแแแแก แจแแแแแ, แแแแจแแ แ แแฎแฃแ แแแ.
แแแ แแแแแ - แซแแ แแแแแ แแแแแแแ แแแแ แจแแขแงแแแแแแแแแแก แแแแแขแแแแก แแแกแแฆแแแแ.
แแก แฌแแ แก แแแแแขแแแก แแ แแแแแ แจแแกแแแแฎแแ, แแแแฌแแแแก แแแแแขแแแแก แแแแแ แแแแก, แแแแแแแแก แแแแแกแขแฃแ แแแแก แแแแแขแแแแก แแแแแแกแ แแ แแแแแ แจแแขแงแแแแแแแแก แแแฌแแแแแแกแแแแก แแ แแแแแแแแก แแแแฎแแแแแก แแแแแ แแฃแแ แแแแแขแแแแก แฎแแแแฎแแ แแแฌแแแแแแกแแแแก. แแแแแ แจแแขแงแแแแแแแแก แฌแแ แแแขแแแแ แแแฆแแแแก แจแแแแฎแแแแแจแ, แแแแจแแ แ แแแแแแแก แแแแแแแ แแแแแจแ แแแกแ แฃแแแแฃแแ, แฌแแแแแฆแแแแ แจแแแแฎแแแแแจแ, แแ แ แแแแแก.
แแแกแ แฃแแแแฃแแ โ แแแแจแแ แแก แแแฎแฃแ แแ แแแแแ แจแแขแงแแแแแแแแก แฌแแ แแแขแแแแ แแแฆแแแแก แจแแแแฎแแแแแจแ.
แแก แแแแแแแ แแแแ แแฃแชแแแแแแแแ แจแแขแงแแแแแแแแก แจแแแ แแแแกแแแแก แแ แแ แจแแแแฎแแแแแกแแแแก, แ แแแแกแแช แจแแขแงแแแแแแแแก แแแฌแแแแแแก แแแแแกแขแฃแ แแแ แแแแแแ แแ แแแแแแแแแแก แแแแแ. แแ แแแแแแแ แแแแแแแ แแแกแแแ แฎแแแแ แแ แแแก แแแแฌแฃแ แแแ, แแแแ แแ แแแแจแแ แ แฌแแ แแแขแแแแ แแแฎแฃแ แฃแแแ แแแแแแแ.
แฃแคแ แ แฆแ แแแ แจแแแแแ แแแแ. แแแแแชแแแแก แแแแขแ แแแแก แแแแงแแคแแแแแ
แกแแแแแแ 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);
}
แงแแแแแ แจแแขแงแแแแแแแแก แแแแแชแแแแกแแแแก แแฅแแแแแ แกแขแ แฃแฅแขแฃแ แ, แ แแแแแแช แจแแแชแแแก แแแคแแ แแแชแแแก แแแแจแแ แแก แจแแกแแฎแแ. แแกแแ แกแขแ แฃแฅแขแฃแ แแก แ.แฌ แแแแจแแ แแก แฉแแแแฌแแ แ.
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;
//...
}
แฃแคแ แ แฆแ แแแ แจแแแแแ แแแแ. แจแขแแขแแแ
แกแแฎแแแแฌแแคแแแแ แแฎแแ แชแแแแแแแ แกแแแแแแ UDP แแ แแขแแแแแแก แกแแฎแแแแฌแแคแ แแแแฅแแแแก, แกแแแแช แฎแแแแ แแแแแขแแแแก แซแแ แแแแแ แแแแฃแจแแแแแ. แแแกแขแ แแฅแขแฃแแ แแแแกแ ReliableUdpState แฃแแ แฃแแแแแงแแคแก แแแขแแ แคแแแกแก แกแแฎแแแแฌแแคแแกแแแแก:
แแ แแขแแแแแแก แแแแแ แแแแแแ แฎแแ แชแแแแแแแ แแแแแ แฌแแ แแแแแแแแแ แแแแกแแแแ, แแแแฎแแแ แ แแแแกแแแ แแ แแแ, แ แแแแแแช แฃแแ แฃแแแแแงแแคแก แกแขแแขแแแฃแ แแแแแแแแก, แ แแแแ แแชแแ, แแแแแแแแแ, ReliableUdp แกแแแแฃแ แแก แแแแแ แแแแจแแ แแก แฉแแแแฌแแ แแแแ.
แจแแแแแแ, แฉแแแ แแแขแแแฃแ แแ แแแแแแฎแแแแแ แแแขแแ แคแแแกแแก แแแแแแแแแก แแแแฎแแ แชแแแแแแแก, แ แแแแแแแช แแแแกแแแฆแแ แแแแ แแ แแขแแแแแแก แซแแ แแแแ แแแแแ แแแแแแก.
DisposeByTimeout แแแแแแ
DisposeByTimeout แแแแแแ แแแกแฃแฎแแกแแแแแแแแ แแแแจแแ แแก แ แแกแฃแ แกแแแแก แแแแแแแกแฃแคแแแแแแ แแ แแแก แแแแฌแฃแ แแแก แจแแแแแ แแ แฌแแ แแแขแแแฃแแ/แฌแแ แฃแแแขแแแแแ แจแแขแงแแแแแแแแก แแแฌแแแแแแแ.
ReliableUdpState.DisposeByTimeout:
protected virtual void DisposeByTimeout(object record)
{
ReliableUdpConnectionRecord connectionRecord = (ReliableUdpConnectionRecord) record;
if (record.AsyncResult != null)
{
connectionRecord.AsyncResult.SetAsCompleted(false);
}
connectionRecord.Dispose();
}
แแก แแฎแแแแ แกแแฎแแแแฌแแคแแจแ แแแ แซแแแฃแแแ แแแกแ แฃแแแแฃแแ.
แแแกแ แฃแแแ.DisposeByTimeout:
protected override void DisposeByTimeout(object record)
{
ReliableUdpConnectionRecord connectionRecord = (ReliableUdpConnectionRecord) record;
// ัะพะพะฑัะฐะตะผ ะพะฑ ััะฟะตัะฝะพะผ ะฟะพะปััะตะฝะธะธ ัะพะพะฑัะตะฝะธั
SetAsCompleted(connectionRecord);
}
ProcessPackets แแแแแแ
ProcessPackets แแแแแแ แแแกแฃแฎแแกแแแแแแแแ แแแแแขแแก แแ แแแแแขแแแแก แแแแแขแแแแ แแแแฃแจแแแแแแแ. แแแ แแแแ แแแ แแแแแ แแ แแแแแขแแก แแแแแแแแแก แขแแแแแ แแก แกแแจแฃแแแแแแ.
แแแแแแแ แแแแแจแ แแแ แแแแแ แแแแแแ แแแ แซแแแฃแแแ แแ แแแกแฃแฎแแกแแแแแแแแ แแแแแ แแฃแแ แแแแแขแแแแก แจแแแแฌแแแแแแ แแ แแแแแแแ แแแแแแ แแแแแกแแแแแ แแแกแ แฃแแแแฃแแ, แแแแ แแแแแขแแก แแแฆแแแแก แแ แฌแแ แแแขแแแฃแแ แจแแแแฌแแแแแก แแแแแแก แจแแแแฎแแแแแจแ
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.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.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.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));
}
แแแแแแแ แแแแแจแ แแแ แแแแแ 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);
}
}
แแแแแแแ แแแแแจแ แแแกแ แฃแแแแฃแแ แแแแแแแก แแ แแแแแ แแ แแแแชแแแแ แจแแขแงแแแแแแแแก แแแแแแแแ แฌแแ แแแขแแแฃแแ แแแฌแแแแแแก แจแแกแแฎแแ.
แแแกแ แฃแแแ. ReceivePacket:
public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
// ะฟะพะฒัะพัะฝะฐั ะพัะฟัะฐะฒะบะฐ ะฟะพัะปะตะดะฝะตะณะพ ะฟะฐะบะตัะฐ ะฒ ัะฒัะทะธ ั ัะตะผ,
// ััะพ ะฟะพัะปะตะดะฝะธะน ack ะฝะต ะดะพัะตะป ะดะพ ะพัะฟัะฐะฒะธัะตะปั
if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
{
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
}
}
แแแแแขแแก แแแแแแแแแก แแแแแแ
แแแแแแแ แแแแแจแ 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.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 );
}
}
แฃแคแ แ แฆแ แแแ แจแแแแแ แแแแ. แแแแจแแ แแแแก แจแแฅแแแ แแ แแแแงแแ แแแ
แแฎแแ, แ แแแแกแแช แฉแแแ แแแแฎแแ แซแแ แแแแแ แแแแแแแ แแแแแแ แแ แแแแแแแ แแแแแแแก แแแแฃแจแแแแแแก แแแแแแแแ, แแแแแ แฉแแแแแงแแ แ แแแแแแแแ แแแแแแแแ, แแฃ แ แแแแ แแฃแจแแแแก แแ แแขแแแแแ แชแแขแ แฃแคแ แ แแแขแแแฃแ แแ.
แแแแแชแแแแ แแแแแชแแแแก แแแแแ แแแ แแแ แแแแฃแ แแแ แแแแแจแ:
แแแขแแแฃแ แแ แแแแแฎแแแแ แจแแฅแแแ แแแแจแแ แแก แฉแแแแฌแแ แ แแแ แแแแ แแแแแขแแก แแแกแแแแแจแแ แแแแแ แแ แแแแแแแแแกแแแแก. แแแแแชแแแ แงแแแแแแแแก แแแแชแแ แแแฃแแแ แแแแแแแชแแแก แแแแ , แ แแแแแแช แฃแฌแแแแแก แแแแแแแแแก แจแแขแงแแแแแแแแก 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);
}
แแแ แแแแ แแแแแขแแก แแแแแแแแแก แจแแแแแ, แแแแแแแแแ แจแแแแก แแแแแแแ แแแแแจแ แแแแแแแแแก แชแแแแ - แแแแแแแแ แแแแแขแแก แแแฌแแแแแแก แแแแแกแขแฃแ แแแแก.
แแแแฆแแแ แแฎแแ แ, EndReceive แแแแแแแก แแแแแงแแแแแแ, แแฆแแแก แแแแแแแแแ แแแแแขแก, แฅแแแแก แแฎแแแก แแแแจแแ แแก แฉแแแแฌแแ แ แแ แแแแแกแชแแแก แแ แแแแแขแก, แฌแแแแกแฌแแ แแแแแแแแแแแฃแแ แกแแแแฃแ แแ, แแแแฃแจแแแแแแก แแแแแแแ แแแแแก 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);
}
}
แฃแคแ แ แฆแ แแแ แจแแแแแ แแแแ. แแแแจแแ แแก แแแฎแฃแ แแ แแ แแแก แแแแฌแฃแ แแแกแแก
แแแแแก แแแขแแ แแแ แกแแแแแแ UDP-แแก แแแแจแแแแแแแแแ แแแฌแแแแ. แแแแแแฎแแแแ แแแแแแแแ, แ แแแแกแแช แจแฃแแแแแฃแ แ แแแแแซแ แแแ แแแฎแแ แฎแแ แแ แแแแแชแแแแ แแแฌแแแแแ แแ แแแ แแแแแ แแฃแแแแแ แจแแฃแซแแแแแแ แแแฎแแ.
แแแแจแแ แแก แแแฎแฃแ แแแก แแแแแ แแแ แแแแแแแ:
แ แแแแ แช แกแฅแแแแแแ แฉแแแก, แแแแแแแแแแก แกแแแฃแจแแ แขแแแแแ แ แแฌแงแแแ แแแแแขแแแแก แแแแแแก แแแแแแแแแกแแแแแแ. แแก แฎแแแแ แกแแฎแแแแฌแแคแแก SendPacket แแแแแแจแ แแแแแแแแแก แชแแแแ.
แกแแแฃแจแแ แขแแแแแ แแก แฉแแ แแแ (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 แแแแแแแ. แแแ แแแแแ
แกแแแฃแจแแ แขแแแแแ แแก แฉแแ แแแ (แแฌแงแแแแก แแแแแแแ แแแแ):
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 แแแแแแ, แกแแแแช แแแแแแก แแแแแ แแฃแแ แแแแแขแแแ แแ แแแ แแแแแ แแแแแแแแแ แฎแแแแฎแแแ แแแฌแแแแแแก แแแแฎแแแแ.
แฎแแแแฎแแ แแแฌแแแแแแก แแแแฎแแแแแแแก แแแแแแแแ (แจแแแ แแแแก แแแแแแแ แแแแ):
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 แชแแแแแ แแแงแแแแแฃแแแ แแแ แแแแแ. แแก แชแแแแแ แแแกแฃแฎแแกแแแแแแแแ แกแแแฃแจแแ แขแแแแแ แแก แแแแแขแแแ แแแแแ.
แแแแแแแแแแก แแฎแ แแ, แกแแแฃแจแแ แขแแแแแ แ แแกแแแ แแแแฅแแแแแแแ แแ แแแแ แแแแแแแแแแ แแแแแขแ แฎแแแแฎแแ แแแแแแแแแ.
แแแแจแแ แแก แแแฎแฃแ แแแก แขแแแแแ แแก แฉแแ แแแ (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 แฌแแแ.
แแชแแ แ แฎแแแก แจแแแแแ, แแแแฆแแแแก แแฎแแ แแก แแแฅแแแแ แขแแแแแ แ แแแแแ แแ แแแแแ, แแแแแ แแแแแแแแแ แแแแฎแแแแแแ, แ แแก แจแแแแแแแช แแฌแงแแแ แแแแจแแ แแก แแแฎแฃแ แแแก แขแแแแแ แ แจแแแแแแแแแ แแแแจแแ แแกแแแแก.
แ แแแแกแแช แแญแแแ แ แขแแแแแ แ แแฃแจแแแแก, แแ แแแ แแแแจแแ แแก แฉแแแแฌแแ แแก แงแแแแ แ แแกแฃแ แกแ แแฎแกแแแแ. แแแแแแแแแ แแชแแแแแแก แแแฌแแแแแแก แฌแแ แฃแแแขแแแแแแแก แแแแแ แแแแแแแก แแแแแแแชแแแจแ (แแฎแแแแ แกแแแแ UDP API).
แแแแจแแ แแก แฉแแแแฌแแ แแก แ แแกแฃแ แกแแแแก แแแแแแแกแฃแคแแแแ:
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 แแแกแแแจแ แแ แแแแแแแแแ แแแแฎแแแแ แฎแแแแฎแแ แแแฌแแแแแแแ.
แแแแฎแแแแแก แแแแแแแแ แแแแแขแแแแก แฎแแแแฎแแ แแแฌแแแแแแแ (แแฌแงแแแแก แแแแแแแ แแแแ):
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));
}
แฎแแแแฎแแ แแแแแแแแแแ แแแแแขแ (แแแแแขแ #3 แแแแแ แแแแจแ) แแแแฆแแแ แจแแแแแแแแแ แแแแจแแ แแ. แจแแแแฌแแแแฃแแแ แแแแฆแแแแก แคแแแฏแแ แ แกแแแกแแ แแฃ แแ แ แแ แแแแแชแแแแ แแแ แแแแฃแ แ แแแแแชแแแ แแฆแแแแแ.
แแแแฆแแแแก แคแแแฏแแ แแจแ แแแ แขแงแแแแแก แจแแแแฌแแแแ (แแฌแงแแแแก แแแแแแแ แแแแ):
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);
}
// ...
}
แกแแแแ UDP API
แแแแแชแแแแ แแแแแชแแแแก แแ แแขแแแแแแแ แฃแ แแแแ แแฅแแแแแแแก แแแแแแ, แแ แแก แฆแแ แกแแแแ 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)
แแแกแแแแ
แแ แกแขแแขแแแจแ แแแแ แ แ แแ แแ แแ แแก แแฆแฌแแ แแแ. แแแแแแแก แจแแกแแขแงแแแกแ แแแฅแแแแแแแแ, แแแแแแแแแแกแแก แแ แจแแชแแแแแแแก แแแแฃแจแแแแแ, แแกแแแฅแ แแแฃแแ แจแแขแงแแแแแแแแก แแแแแแแแแก แแแแแแแแแก แแแแแ แแแ. แแแแ แแ แแ แแขแแแแแแก แแ แกแ, แแแแแขแแแแก แแแแฃแจแแแแแแก แแแแแแแก แแฆแฌแแ แ, แแแแจแแ แแก แแแแงแแ แแแ แแ แแแแแแแก แแแแฃแจแแแแแ, แแแกแแแแแ แฃแแแ แแงแแก แแฅแแแแแแแก.
แกแแแแแแ แแแฌแแแแแแก แแ แแขแแแแแแก แแแแแแกแขแ แแ แแแฃแแ แแแ แกแแ แกแแแแแ แแกแแ แซแแแแ แ แแ แแแฅแแแแแ, แ แแ แแแแแแแงแแคแแแแก แแแ แ แแแแกแแแฆแแ แฃแแ แแแแฎแแแแแแ. แแแแ แแ แแ แแแแแ แแแแแแแขแ, แ แแ แแฆแฌแแ แแแ แแแแฎแแ แชแแแแแแ แจแแแซแแแแ แแแฃแแฏแแแแกแแแก. แแแแแแแแแ, แแแแขแแ แฃแแแ แแแแแแแก แแแกแแแ แแแแแ แแ แขแแแแแ แแก แแแ แแแแแแแก แแแแแแแฃแ แแ แจแแกแแชแแแแแแ, แแ แแขแแแแแก แจแแแซแแแแ แแแแแแขแแก แแกแแแ แแแฅแแแแแแแแ, แ แแแแ แแชแแ แแแชแฃแ แแแแก แคแแแฏแแ แ แแ RTT, แแกแแแ แกแแกแแ แแแแแ แแฅแแแแ MTU-แแก แแแแกแแแฆแแ แแก แแแฅแแแแแแแก แแแแแ แแแ แแแแจแแ แแก แแแแแซแแแก แจแแ แแก (แแแแ แแ แแฎแแแแ แแแแ แจแแขแงแแแแแแแแแแก แแแแแแแแแก แจแแแแฎแแแแแจแ). .
แแแแแแแแ แงแฃแ แแแฆแแแแกแแแแก, แแแแ แแฅแแแแก แแแแแแขแแ แแแก แแ แแแแแแขแแ แแแก.
PS แแแแแแแก, แแแกแแช แแแแขแแ แแกแแแก แแแขแแแแแ แแ แฃแแ แแแแ แกแฃแ แก แแ แแขแแแแแแก แขแแกแขแแ แแแ, แแ แแแฅแขแแก แแแฃแแ GitHube-แแ:
แกแแกแแ แแแแแ แแแฃแแแแ แแ แกแขแแขแแแแ
- TCP แแ แแขแแแแแแก แกแแแชแแคแแแแชแแ:
แแแแแแกแฃแ แแแแแ ะธะฝะฐ ััััะบะพะผ - UDP แแ แแขแแแแแแก แกแแแชแแคแแแแชแแ:
แแแแแแกแฃแ แแแแแ ะธะฝะฐ ััััะบะพะผ - RUDP แแ แแขแแแแแแก แแแแฎแแแแ:
draft-ietf-sigtran-reliable-udp-00 - แกแแแแ แแแแแชแแแแ แแ แแขแแแแแ:
rfc908 ะธrfc1151 - UDP-แแ แแแขแแแแก แแแแแกแขแฃแ แแแแก แแแ แขแแแ แแแแฎแแ แชแแแแแแ:
แแแฆแแ แแฅแแแแ แฅแกแแแแก แกแ แฃแแ แแแแขแ แแแ .NET-แแ แแ UDP-แแ - แกแขแแขแแ, แ แแแแแแช แแฆแฌแแ แก NAT-แแก แแแแแแก แแแฅแแแแแแแแก:
Peer-to-Peer แแแแฃแแแแแชแแ แฅแกแแแแก แแแกแแแแ แแแแแก แแแแ แแแแแแแแจแ - แแกแแแฅแ แแแฃแแ แแ แแแ แแแแ แแแแก แแแแแแแก แแแแแ แแแ:
CLR แแกแแแฅแ แแแฃแแ แแ แแแ แแแแ แแแแก แแแแแแแก แแแแแ แแแ ะธแ แแแแ แแแแแแฎแแ แชแแแแแ IAsyncResult แแแแแแแแก แแแแฃแจแ - แแกแแแฅแ แแแฃแแ แแ แแแ แแแแ แแแแก แแแแแแแก แแแ แขแแ แแแ แแแแชแแแแแแ แแแคแฃแซแแแแฃแ แแกแแแฅแ แแแฃแ แจแแแแแแแ (APM TAP-แจแ):
TPL แแ แขแ แแแแชแแฃแแ .NET แแกแแแฅแ แแแฃแแ แแ แแแ แแแแ แแแ
แฃแ แแแแ แแฅแแแแแแ แกแฎแแ แแกแแแฅแ แแแฃแ แแแแฃแจแแแแแ แแ แขแแแแแแแ
แแแแแฎแแแแ: แแแแแแแแ
แฌแงแแ แ: www.habr.com