α’αα·αααΊαα·αααΆαααααΆααααααΌαααΆααΌαααα αΎαα αα·ααΈααΆαααααΆαααα½αααα’ααΈαααΊαα·α - UDP ααααΌαααΆαααααΎααααααααα·ααΈαα·αααααΉαααααΎααααΈαααααΌααα·αααααα αα·αααΆαα
αΆααααααΆαααα»ααααααα ααα»αααααααααΆαααααααααΌαααΆααααααΆαα "ααΈαα½ααα
αα½α" αααΆαααααΆαααααααΆαα αααααΆαααααΆααα
ααΆααααΆααααααααααΆ αα·ααΈααΆααααααΆαααΆαααααΎααααΆααααΆα
αααΎαααααα·αααΆαααααααα»αααΈαα»ααα αααααΆαααΆαααΆααααα ααΆαααααααΆααααα·ααΈααΆα ααΌα
ααΆαααααααΆαααΆααΆαα·αααΆαααα
ααΆα‘αΎαα α’αααααααααα·αααααΆα’αααΈααΆαα’αα»αααααα·ααΈααΆαα
ααα
αΆααααααΆαααΆαααΆααΆααΎ UDP α
ααΆαα·ααΆ:
αα·ααΈααΆααααα DisposeByTimeout αα·ααΈααΆαααααααααΎαααΆααααα αα αα·ααΈααΆαααααααα½ααααα αα αα·ααΈααΆαααααααααΎαααα αα
ααΆαα»
ααααΆααααααααααΎαααα’αα·αααΊαα·ααααααααΆααΆααααααα’αΆααααααΆαααΌα
ααααΆ αααααααΆααααΈαα½ααααΆαα’αΆααααααΆα IP ααα αα·ααααα½αααα α αΎαα’αΆα
ααααΆαααααααααααααΆααααΆαα½αααααΆααααααααααα α₯α‘αΌααααα’αα·αααΊαα·αααΆαααΆααα·αααΆαααααΆαααααααααααααααααΆ - ααααααα½αααα’αΆααααααΆα IP ααααα·ααααααααΆα
αααΎααααααΆαα’αΆααααααΆαα―αααααΆαααα
ααΈαααααα§ααααα NAT α
ααααΆααααααααααα’ααΈαααΊαα·ααααααΊααααΉαααααΌααααααααααΆαααααααΆααααΆαααααΆααααααα’αα·αα·αα-αααΆαααΈααα αααα’αα·αα·ααα’αΆα αα αααα»ααααααΆαα―ααα α αΎααααΆαααΈαααααΆαα’αΆααααααΆααααα ααα»ααααααΆαααααΎαααΆαααααΆααααααΆααααΆααααααΆαααααααααΆααααααααΆααααΈααααΆα αααααα αααααΆαα―αααα ααΆααααααΆαααααααααΆαααααΆαααααΆααααΈαααΊααΆαααΆααααααΆαααααααΆαααααααα·ααΈααΈααααΆαα αα·ααα ααααΌα ααΆααΆααααααΌαααα‘αα (Skype) ααΆαααα½αααΆαααΈα ααααΆααα ααΆαααα»αααααΌααα (TeamViewer) α¬α ααααα’αα‘αΆαα
αα·ααΈααΆαααααααααΆαααααα·αααααΆααααα»ααα½ααααααΆαααααααΎαααΆααααααΆααααΈαα½ααα αα½ααααΆαα§ααααααα ααΎαααααΆαα―αααααααααααααΆααααΌαααΆαααα α ααΆααΆαααΆααααααα αα αα ααααααααααααΌαααΆαααααΎααΆααΌαα αααα»αααΆαα½ααααααα·ααΈαααααα’ααααΎαα·ααΈααΆα UDP α
ααα»ααααααααα·αααΎαααααα·ααΈααααα’αααααΆαααΆαααΆαα ααα αΆααα·αααααααααααΆαααΆαααΆααΆ ααΆα§ααΆα ααα α’ααααααααα―αααΆααααΆααα»αααααΌααα αααααΆαααααΎ UDP ααΉαααΆαααΆαααααΆαααΆα αααΎααααααΆααα UDP αα·ααααααΆαα·ααΈααΆαα ααα αΆααααααΆαααΆαααΆααΆ α αΎααα·ααααααααΆαα ααα αΆααααα ααααααααΆαααΆαααααΆααααααα αα·αααΌα TCP ααα αα·ααΈααΆαα
αααα»αααααΈααα ααΎααααΈααΆααΆααΆαααΌαααΆαα ααα αΆααααα ααααααααΆα ααΆααααΌαααΆαααΆαααΆαααΎααααΈα’αα»αααααα·ααΈααΆααααααΆαααααααα·ααΈαααααααααα»αααΆαα αΆαααΆα α αα·αααααΎαααΆαααΎ UDP α
αααα»αα ααααααααααΆααααααΆααααΆααΆααα αα αααααααΆαααααα TCP αααααΆαααααααΎαααΆααααααΆαα TCP αααΆαααααΆαααα αααα»ααααααΆαα―αααααααααααααΆ ααα»αααααααααΆαααΆαααααααΆαααΆαααΆαααααααααΆααααΆαααα§ααααα NAT ααΆα αααΎα ααΆααααααΆααΆαα·αααααΌαααΆαα αΆαααα»αααΆααΆαα·ααΈα αααααααα»αααΆααααααΆαααααααα ααααΆααααααααα
αααααΆααα’αααααααααα ααααααααα αααα»αααΉααααααααααΎααΆαα’αα»αααααα·ααΈααΆαα ααα αΆααααααΆαααΆαααΆααΆααα»αααααα ααΆαα’αα»αααααα αα αααααααΆαααααα UDP ααΉαααααΌαααΆααα·αααααΆαα αααα»αα’αααααααΆααααααα
αααααΌαααΆααα·ααΈααΆα
- ααΆαααααααααα ααααααααΆααααα’αΆα ααΏαα»αα α·αααααΆαααααΌαααΆαα’αα»ααααααΆααααααααααΆαααα·αααα‘αααα·αααααΆα (α α ααΆααΆαααα½αααααΆααααΆαα·αααααΆα)
- αααααΌαααΆααααααΆααααΆαααααααα·ααααααααααααααααααααα·αααααΆα i.e. αα·ααΈααΆαααααΌααααααααΆαααΆααααααΌααααααααα ααααααααΆαααααα·αα αΆαααΆα α
- ααΆαα½αααα’αΆα αα»αα ααααααααΆααααααΆααααΆαα ααα αΆα (αααααααΆααααα»αααΆαααααΎαααΆαααΆαα·ααΈααΆα UDP "αα»ααα")
- αααααααΆααααα»αααΆαα’αα»ααααααααααΆααααααααΆαααααΆαααΆααααααΆααααΈααΆαααΈαα½αα
- α―αααΆααΌαααααΆαααααΆαααααααα·ααααααααΎαα·ααΈααΆαααααΌαααααΆααΆα
αααααΌαααΆαααΆαααααααΆαα
αααΎαααααααααΆααΉααααααΌαααΆααα·ααΈααΆααα·αααααααααα’αΆα
αα»αα
α·αααααΆααααααΆααα·αααααΆαα
αααα»α
ααΎααααΈαααααΈαααααΌαααΆαααΆααααα ααΌααααα‘ααααΎααααααααΆααααΆαααααααα·αααααααααΆαααααΆαααααααΆαααΈααααααααΎαα·ααΈααΆα TCP αα·α UDP α α’αα»ααααΆαα±αααααα»αααααΈααΆααααΈαααΎαααΉαααΆααααα
αααα½αααΆααα
ααΆαααααααα·αααααααα·αα’ααααααααααΎ TCPα
ααΌα
αααα’αααα’αΆα
ααΎαααΎαααΈααααΆααααΆα αααα»αααααΈααΆααααααααα
ααααααααΆα TCP ααΉαααααΎααααα
ααααααααΆααααααΆαα α αΎαααΆαααΆαααααΆαα
α’αααααααΎααααα½αααα
ααα½αααααααααααΆααα
ααΆαααααααα·ααααααααΆαααααα·ααΈααΆα UDPα
UDP αα·αα
αΆαααα·ααΆαααΆααααααααααΆαααΆαααααααΆαα½αα‘αΎαα ααΆααααα½ααα·αα·αααααα α»αααααΆααααααΌααα
αααα»ααα·ααΈααΆα UDP ααΊααΆααΆαααα½ααα»αααααΌαααΆαααααα»ααααααααα·ααΈα
ααΆαααααΎαααα α»ααα αααα»ααα·ααΈααΆα TCP ααααΌαααΆααααααα αααααΆααααααΎαααΆααααααΆααααΆαα½αααααΆαααααα αα αααααΆαα»αααααΆαααΆαααααΆααααααΆααααα αααα αΆαααΈα ααα½ααααααααΆαααααΎαα αααα»αααααααΆαααααα ααααααααΆαααΈαα½αα αα·αααΆαααΌαααααΉααααααΆαααααααααααΎαααααα½αααααΆααα
ααΎαααΈαααααα ααΎααααΈαααααΎαααΆαα’αα»αααα (α§. ααααΎα αααΎαααΆααα½ααααααααααα·αααα½αααΆαααΆαααα½αααααΆαα) αα·ααΈααΆα TCP ααααΎα’αααΈαααααα α ααΆ αααα’α½α αααααΌα - α ααα½ααααααα·αααααααααα’αααααααΎαααααααααααΉαααΆααΉαααα½αααΆαα
αααααΆααααααααΆαααααααα’αααΈαα·ααΈααΆα TCP ααΌαααΎα
ααΈααΆαααΎ ααΆα αααΆααααΆααααΆααΎααααΈαααααΎααα·ααΈααΆααααααΌαααΆααααα’αΆα αα»αα α·αααααΆαααΎ UDP (ααα αααα α ααΆ UDP αααα’αΆα αα»αα α·αααααΆαα) ααΆααααΌαααΆαααΆαααΆαααΎααααΈα’αα»ααααααααααΆαααααααα·ααααααααααααααΉα TCP α αααααΊα
- αααααΆαα»αααααΆαααΆαααΆααααααΆαα
- ααααΎααααααααααα
- ααααΎαααα αααααααΆαααα·ααα
- ααααΎααααααΆαααΎααααα’α½α ααΆαααα ααΎααααΈαααααΎαααααΎαααΆααααα·ααΈααΆα
ααΎαααΈααααααα’αααααααΌαααΆα:
- ααΆαααααΆααααΆαα αΆααααααΎαααΆα ααΎααααΈαααα ααααααΆααααααΆααααΆααααααΆαα
- ααααααααααΆα α»ααααα ααααααΆα ααΎααααΈαααααΌαααΆααααααΆαααα½ααα αααααα·ααΈααΆαααΎ αα·ααααα ααααααΆααα·ααΈααΆα
- α’αα»ααααΆαα±αααα·ααΈααΆαααΆααααΆααααααΆααααααΆααααΎααααΈαα·αααααααΆααααααΆααααΆαα ααα αΆαααΎααααΈααααΎαααΆαααΆ UDP "ααα·αα»ααα"
ααααΆα UDP αααα’αΆα
αα»αα
α·αααααΆαα
ααΌαα
αΆαααΆ UDP datagram ααααΌαααΆααα»αααααααααα»α IP datagramα αααα
ααααααααΆα UDP αααα’αΆα
ααΏαα»αα
α·αααααΆαααααΌαααΆα "αα»α" αααΆαααααΉαααααΌααα
αααα»α UDP datagram α
ααΆαααα
ααα
ααααααααΆ UDP αααα’αΆα
αα»αα
α·αααααΆαα
αα
ααΆααααααααααααααααΆ UDP αααα’αΆα
ααΏαα»αα
α·αααααΆαααΊααΆααααααΆαα:
- αααααΆαα· - αααααααααααααααα αα
- MessageType - ααααααααΆααααααααΎααααααααα·ααΈααΆαααΎααΎααααΈααΆαααΆαααΆααααΆαα
- TransmissionId - α ααα½αααααΆααααααΌα αα½αααΆαα½αααΉαα’αΆααααααΆα αα·αα αααααααα’αααααα½α αααααα’ααααααααΆαααΆααααααΆαααααα½ααααα
- ααααααα αα - ααααααα αα
- αααααΎα - αααααΎααα·ααΈααΆαααααααα αααα»αβααααΈβααβαααα ααβααΈαα½α ααΆβααααΌαβααΆαβααααΎβααΎααααΈβαααα αΆαβααα αβααβααΆα
αααααΆαα·ααΆαααΌα ααΆααααααα
- FirstPacket - αααα ααααααΌαααααΆα
- NoAsk - ααΆααα·ααααααΌαα±ααααΆαααααααΆαααα½αααααΆααααΎααααΈααΎαααααΎαααΆαααα
- LastPacket - αααα ααα α»ααααααααααΆα
- RequestForPacket - αααα ααααααααΆααααααΆαα α¬ααααΎαα»ααααα ααααααααΆααααααΆαα
αααααΆαααααΌαα
αααα·ααΈααΆα
αααααΆα UDP αααα’αΆα αα»αα α·αααααΆαααΊαααααααΎααΆααααααΌαααΆααααααΆαααΆαααΆααΆαααΆαααααΆααααΈα ααΆααααΌαααα’αΆα αααααΎαααΆααααααΆααααΆαα½αααΆααΈααααΆααααα ααΎααααΈαααααΎαααΆααααααΆαα α’αααααααΎααααΎαααα ααααααααΆααααααΆαααα FirstPacket ααΆαααααΎααααααααΉαααΆααααααΆααΆααααααΆααααααΌαααΆααααααΎαα‘αΎαα αααα ααααααααΆαααααΎαααααΆααα’αα α¬αα·ααΆααααααΆαααα αααα ααααααααΆαααα½αααααΆαα ααααααααααααααααααααα’ααααααααα αααα αα½αα αααΎαααΆαααααααααα ααααααααααα»ααααααα ααααααααΆααααααα½αααΆααααααααααα ααΆααααααΎααααααΆαααααα ααααααααΆαααααΌααααααΆαααααΎααΊααΆααα αααααΆαα
ααααααΆαααααααααααΆαααααααΌαααΆαααααΎααΎααααΈαααα
ααααΆααααααΆααα ααα LastPacket ααααΌαααΆαααααααα
ααΎαααα
ααααααααΆαα
α»ααααααααααΆαα αα
αααα»ααααα
ααααααΎααα α
ααα½ααααααα
ααααααααΆαα
α»αααααα + 1 ααααΌαααΆαα
ααα’α»ααααα αΆα ααααααααΆαααααααααα½αααΆααααααΆααΆααααααΌαααΆααααααααααα
ααααΆααααΆαβααΆαβαααααΎαβαα·αβααΆαβαααα
ααβααΆαβαααααΆααα
αα
ααααααααΆααααααΆααααααΌαααΆααααααΎαα‘αΎα ααΆαααααααα·ααααααα
αΆααααααΎαα αα·ααααααααααΌαααΆααααααΌαααΆααααα»ααααααα
ααααααααΆαα αααα»αααΈαα½αα ααΎαααααααα½αα
α»αααααα ααΆααααα
ααααααααΆαα
ααα½ααααα ααΆααααΎααΉαααα ααααα’α½α
ααα½α/αααααΌαα αααα»ααα·ααααααα
α»ααααααα’αΆα
ααΆααααα
ααααααααΆααα·α
ααΆαα αααααΆααααΈααααΎαααα»αααΈαα½αα ααΆααΈααααΎαααα
αΆαααΆααααααΆααααΆαααΉααααααΌα α¬ααααΎααΎααααΈαααααΌααααα
αααααααΆααααΆαααΆααααΈ ααααα»αα±αααααα’α½α
ααα½α/αααααΌαααΎαααΎααααΈααα½αααΆαααααΎαααα αααααΆααααΈααα½αααΆαααΆααααααΆααααΈααΆαααΉααααααΌααααα»α αααα’α½α
ααα½α/αααααΌαααααΆααααααΌα α αΎααααα»ααααααΆαααααα·ααααααααααΌαααΆαααααΎα
ααΆααΈααα½αααα½ααααα
ααα αααα
ααααΈαα½ααααααΌαααΆααα·αα·ααα ααΎααααΈααΎαααΆααΎααΆααααΆαααααα»ααααα’α½α
αααααΌαα¬α’ααα αααα
ααβαα·αβαααα½αβαααβαα·αβααααΆααβα
αΌαβαααα»αβαααα’α½α
βααααΌαβααΆαβα
ααααβα
ααα αααααΆααα ααααα·αααΎααα ααααα·αααΌααααΌαααΆααα½ααα»α α αΎαααΌα
ααααΆαααααΆααα’αααααα½α αα·αα’αααααααΎ ααααααα»αααααΈααααααα»ααααααα
ααααααααΆαααααΌαααΆααααααΌαααααα·αααΆααααα ααααααα’α½α
ααααΌαααΆαααααΌααα
ααα½ααααα
ααααααααΆααααααα»ααααααΆαααααα·αααααα α αΎαααΆααααααΆααα’αααΈααΆαααΉααααααΌαααΊ ααΆαααααΎα ααααα·αααΎαα·αααΌαα·αααααααααα»ααααααααααααααααααααα·ααΈαααααααααααΆαααΆααα αααααΆααααα½ααα·αα·αααααΉαααααΌαααΆαα
αΆααααααΎαααααααα
ααααααααΆααα·αααΆααααααΌαααΆααααααΌα α αΎαααααΎαααααΆααααΆαααΉααααααΌαα‘αΎααα·αααΉαααααΌαααΆαααααΎα
ααααΆααααΆααααααΌαααααα
ααΆαα’ααααα αα·ααααααα·ααΈααααααααααααΆαα·ααΈααΆα
ααΆαα ααα»ααααΆα αααΎααααααΆααααααΆαααα·αα’αΆα αααααΎαααΆαα α§ααΆα ααα ααααα·αααΎααΆααΈααα½ααα·αααΆαα’ααΈαααΊαα·αα αααα»αααααΈααα αα αααααααΆααΆααααααΎαααΆααααααΆαα ααΆααααααΆααααΉαααααΌαααΆααα·ααααα’αααααα ααΆαα’αα»αααα UDP αααα’αΆα αα»αα α·αααααΆαααααΎαααααα·ααΈαααααααααααΈαααΎααααΈααααααααααααΆα’αααααα ααΈαα½α αααααα·ααΈαααααααααααααΎααΆα ααααΌαααΆαααααΎααΎααααΈαααα αΆαααΆαααααΎαααααΈαααΆαααΈαααΈα ααααΆαα ααααα·αααΎααΆααααα αααααα’αααααααΎ ααααααα ααααααααΆααααααΆαααααΎα α»ααααααααΉααααααααααα·αα ααααα·αααΎαααααα·ααΈααααααααααα»αααααααα α’αααααα½α αααααΆααααα½ααα·αα·ααααααα ααααααααΆααααααΆααααααΌαααΆαα’αα»αααα α αΎαααααΎαααααΆααααΆαααΉααααααΌαα‘αΎααα·αααααΌαααΆαααααΎα
α§ααααααααααααααααΈααΈαααΊααααΌαααΆαααΎααααΈαα·αααΆααααααΆαααααα»αααααΈαααααααααααΆαααααααααΆαααααΆααα αααααΆααααΆααΈα’αααααααΎ ααΆα αΆααααααΎαααααΆαααααααΆααααΈαααααα·ααΈαααααααααααααΎααΆααα»αααααα α αΎααααα αΆαααΆαααααΎαααααΈααααΆααααΈα ααααΆαα ααααα·αααΎαα·αααΆαααΆαααααΎααααααα»ααααααααααααΆααααααΆαααα ααΆααααααΆααααααΌαααΆααααα αα α αΎαααααΆαααααΌαααΆααααα ααα αααααΆαααααααααα½α α§αααααααααααααααα·αααααΆααααααΆααααααΌαααΆαα αΆααααααΎααααααΆααααΈαααααα·ααΈαααααααααααΆαααΆααα»ααααααααΈαααα αααααΊα αΆαααΆα αααΎααααΈααΆααΆαααααΆααααΉαααΆαααΆααααααααα ααααααααΆααααααΆααα αα αααααααααααα·ααΈααααααααααα»αααααα ααΆααααααΆααααααααΌαααΆααα·α α αΎαααααΆαααααΌαααΆααααα ααα
ααααΆααααΆαααααΆαααΆααααααΌα UDP αααα’αΆα
αα»αα
α·αααααΆαα
αααααΆααααααα·ααΈααΆαααααΌαααΆαα’αα»αααααα
αααα»ααααΆαααΈαααααααααα αααααααααΈαα½ααααα½ααα»αααααΌαα
αααααααααα·ααααΆααΆααααΆααααααααΎαααΆααααα
ααααααααΆαα
ααααΆααααΆααααα UDP αααα’αΆα
αα»αα
α·αααααΆαα
βαα·α - αα·ααααααΆαααααα ααΆααΆα
ααα»α
α
αΆααααααΎα αα·ααααα
αααααααΆαα automaton α αααααΆαααααα βαα·α αααα»ααααα½ααα·αα·αααααΆααααααΌαααααΌαααΆαααα½α αααα’αα»αααααααΆαααΈααα UDP α’ααααΆα αααααΌααααα
ααααααααΆααα
ααΆααααΆααααααΆααααααααααα α αΎαα
αΆααααααΎαααααΎαααΆαααααα
ααΆαααααΎαααα ααααααΌα - ααααΆαααΆαααααΌααααααΆααααααΆααα ααααΊαα ααααααααΆαααααΌαααΆαααααΎα
αα αααα»αααααΆαααΆαααα αααα ααααααΌααααααΆααααΆαααααααΆααααΌαααΆαααααΎα αααααΆααβααΆαβαααβαα·αβααΆαβααΆαβααααΎβαααααΆαα αααβααΆβααααΆαααΆαβααβαα½αβαααβαααβααΆαβααΆααβααΌαβααααΌαβααΆαβααααΎα
αααααααααΌα - ααααΆαααΆαααΌαααααΆααααααΆααααΆααααααΌααααα ααααΆαα
ααΆαααααΆααααααΌααα ααΆααΈαααα ααΆαααααΎαααα ααααααΌα ααααΌαααΆαα’αα»αααααααααΆααααΈαααα ααααααΌαααααΆαααααΌαααΆαααααΎα ααΆαααα·ααα αααα»αααααΆαααΆαααα αααααΆααααΆαααα½αααααΆαα αα·αααααΎαααααΆααααΆααααααΌαααΆαα‘αΎααα·αααα ααΆαα αΆαα ααααΈααΆααΊα’αΆα ααααΎαα ααΆααααα»αααααΈααΈα - αααα»αααααΈαααααΆααααααΌαααΆαααΆαααααααα¬αααααΆαα’αααααα
αααα ααααΈαα½αααΆαααα½α - ααααΆαααΆαααααΌααααααΆααα’αααααα½αααΆαα
ααΆαα·αα·αααααΆαααααΉαααααΌαααααΆαα αΆααααααΎαααααΆααααααΌα αααααΎααα ααΆααααααααα αΆαααΆα α αα·αααααΎααΆαααα½αααααΆααααααΆαααα½ααααα ααααααααΆαααααΌαα
αααααΆααααΆααααααΆααααα αααααα½α α αΎαααααΌαααΆαααααΎααααα·αααααΎααααα»ααΆαααααΆαααΉααααααΌα αααααΊααΆαααααααα½ααααα αααααΆααααΈααααΎαααΆαααΆααααααα ααΆααααααΆααααααΌαααΆααα·αα
ααα‘αΎα - ααααΆαααΆαααΌαααααΆααααααΆααααΆαααα½ααααα ααααΆαα
ααΆααααααααα ααααααααΆααα αααααααααα»αααααααα’αΆαααα αα·αα·αααααΎαααΆαααΆααααααααα ααααααααΆα ααααΎααΆαααα½αααααΆαααααααΆααααΆαα ααα αΆααααα αααααα ααααααααΆα αα·αααΆαααΆααααΌα αα·αααααΎααααΎαααααΆααααΆαααΉααααααΌαα‘αΎααα·ααααααα ααααααααΆααααααΆααα αααα»αααααΈαααααΆαααα½αααααααααααΆαααΆααααΌα ααΆααααααΆααα αΌααα αααα»ααααα ααΆααααα ααααΎαα·αααΌα αααααα ααΆαα’αααααα ααα
ααΆααααα αα - αα·αααΆααααααΆαααααα»αααααΈααα½αααΆαααΆαααΆααααΌααααααααααα
αααααααααΊα αΆαααΆα ααααααΆααααΆααα½αααααα»αααααΆααααΆα αα·ααααααΆααααααΈαα ααααααααΆααααααΆααααΆααααααΌαααΆαααααΌαααΆαααΆααααααα ααΆαααααΌααα ααΆααα’αααααααΎα ααααΆαααΆααααααααΌαααΆαα αΆαα αααααααΆαα’ααααα ααα»ααααααΆααααααΆααααααΌαααΆαα αΆαααα»αααΆααΆααα·ααααααααααα
ααΆαααααααΈααααα
αα
αααα»αααΌαα α’αααααΆααααα½ααα·αα·αααααΆααααααΌα
ααΆαα»ααααΆαααα½ααα 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 ααα½ααα»αααααΌαα ααααααααΎαααΆααααααααααααα αα α¬αααα ααα α α αααααααΆαα α¬ααΆαααααααααα·ααΈααααααααααααα αΆααααα ααααααααΆαα
α’αΆα
ααα‘αΎα αα·ααΈααΆααααααααααααΌαααΆαααα·ααα αα·αααα½ααα»αααααΌααααα»αααΆααααα½ααα·αα·ααααααα
ααααααααΆααααααΆαα αα·αααΆαααααααα
αααα ααΆααααα
αααααα»αααααΈααα½αααΆααααα
ααααααααΆαα
α»αααααα αα·αααααααΆααααΆααααα½ααα·αα·αααααααααααα
αααα
ααααααΎαααΆαα
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);
}
α’αΆα
ααΆααααα
αα αα·ααΈααΆααααααααααααααααα·ααΈαααααααααααααααα»αααααΎαααΆα α αΎαααααΎααΆααα
ααΆααα’αααααΆαα
ααΆααααα
ααα αααα
ααααααΎαααΆαα
public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
if (connectionRecord.WaitForPacketsTimer != null)
connectionRecord.WaitForPacketsTimer.Dispose();
// ΡΠΎΠ±ΠΈΡΠ°Π΅ΠΌ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΠΌ Π΅Π³ΠΎ ΠΏΠΎΠ΄ΠΏΠΈΡΡΠΈΠΊΠ°ΠΌ
ReliableUdpStateTools.CreateMessageFromMemoryStream(connectionRecord);
}
αα·ααΈααΆαααααααα½ααααα
αα
α’αΆα
αααα
ααααΈαα½αααΆαααα½α ααΆααα·α
αα
α
αααααααα·ααΈααΆαααααααΊααΎααααΈαααααααΆααΎαααα
ααααΆαααααΌααα·αααΆααΆααααααα
ααα»α
αααααΆαα α αΎαααααΎααααΈαααααΌαααΆααααααΆααααα
ααααααααΆααααα½αα
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));
}
α’αΆα
ααα‘αΎα αα
αααα»ααα·ααΈααα½ααααα
ααααααααΆα ααΆαααΆαα
ααααααααΆααααααΌααααα»αααΆαααΈαααα
ααααααααΆαα
αΌαααΎαα‘αΎαα
ααΆααααααΌααααα»α.ααα½ααααα
ααα
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);
}
}
α’αΆα
ααΆααααα
αα ααΆααα·α
αα
αααα½αααααααα·ααΈααΆαααααααΊααΎααααΈααααΎααΆαααα½αααααΆααα‘αΎααα·αααααΆααααααΌαααΆααααααααααα
ααΆααααα
ααα αααα
ααααα½αα
public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
// ΠΏΠΎΠ²ΡΠΎΡΠ½Π°Ρ ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΠΏΠΎΡΠ»Π΅Π΄Π½Π΅Π³ΠΎ ΠΏΠ°ΠΊΠ΅ΡΠ° Π² ΡΠ²ΡΠ·ΠΈ Ρ ΡΠ΅ΠΌ,
// ΡΡΠΎ ΠΏΠΎΡΠ»Π΅Π΄Π½ΠΈΠΉ ack Π½Π΅ Π΄ΠΎΡΠ΅Π» Π΄ΠΎ ΠΎΡΠΏΡΠ°Π²ΠΈΡΠ΅Π»Ρ
if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
{
ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
}
}
αα·ααΈααΆαααααααααΎαααα
αα
α’αΆα
ααΆαααααΎαααα
ααααααΌα αα·ααΈααΆααααααααααααΎαααα
αααα·ααααααααααΌα α¬ααααα·αααΎααΆααα·ααααααΌαα±ααααΆαααΆααααααΆααααΆααααααΌααα ααΆαααΆααααΌαα
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 state):
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 ααα½ααααα
ααααααααΆααααααΆαααααΎ αααααΎαααααΈα αααααααααΆααΆααααααΆαα α αΎαααααααΆαααααα
ααααααααΆαααα ααΆαα½αααΉαααααααΆαααααΆααααααΆαα»ααα
ααΆαααα·ααΈααΆαααααααα½ααααα
ααααααααΆααααααααααααΆααααααΎαααΆα αααα
ααααΈαα½αααΆαααα½α
αααααΎαααΆααααααΆαααα
αααααααα½αα
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);
}
ααΆαααα½ααααα ααααααααΆαααααΌα αα·αααααΎααΆαααα½αααααΆαα (ααααααα½ααααα ααααααΌα):
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 αααααα αααααααααΌα.
ααΎαααααΎαααΆααααααα·ααΈαααααααααααααΎααΆα (ααααΆαααΆααααααΌααααα)α
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 αα·ααΆααΈα
αααααΆααααΆααααααΆααα
αΌα αααααα·ααΈαααααααααα
αΆααααααΎααααααΆααααΈααα½αααΆααααα
αααα·ααααααα
α»αααααα αααααΆααΎαα‘αΎααα
αααα»ααα·ααΈααΆαααααααα½ααααα
ααααααααΆααααααααα ααα‘αΎα
ααΎαααααΎαααΆααααααα·ααΈαααααααααααΆαααΆα (ααααΆαααΆααααααΌααααα»α)α
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 ααααΌαααΆαααααααα ααΆααΆααα·α. α’αααβαααβααα½αβαα»αβααααΌαβαααααΆααβααΆαβα αΆααβααααΎαβαααααα·ααΈβαααααβααααβααααΎβααΆαβα‘αΎαβαα·αα
αα
αααααααΆαα’αααααααΎ αααααα·ααΈαααααααααααααΎααΆαααααααΌαααΆαααα α αΎααααα
ααααααααΆααααααΆαααααΎα
α»ααααααααααΌαααΆααααααΌαα‘αΎααα·αα
ααΎαααααΎαααΆααααααα·ααΈααααααααααααΆαα·αααΆααααααΆαα (ααααΆαααΆααααααααααΌα):
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);
}
}
// ...
}
}
α’αααααααΎααΉαααα½αααααααΎα
ααα
αΆαα‘αΎααα·α α αΎαααααΎαααα
αααααααΆααα ααΆαα½αα±ααααααααααΆααααΆαα
ααααααα’αααααααΎααΆαα
αΆααααααΎααααααα·ααΈααααααααααααΆαα·αααΆααααααΆαααα½α
α αΎαα αΎααα
ααααααααααΎααααΌαααΆαααα½αααΆααααΌαααΆααααααα‘αΎααα·αα
αααααΌααααα
αααααααΆαααααα‘αΎααα·α (ααααΆαααΆαααααααααΆααααααΌα):
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)
ααααααααααΆαααααΎααΆαααΉααα·α - ααααα·αααΎααΆαααΆααα αααα’αααααα½αααααααααα αα·ααα·ααα·α - ααααα·αααΎααΆααααααΆααααααΌαααΆααα·ααααα’αααααα
public bool EndSendMessage(IAsyncResult asyncResult)
ααα
ααααΈααααα·ααααΆα
ααΆαα αααΎααα·αααααΌαααΆααα·αααααΆαα αααα»αα’ααααααααααα ααααααΆαααααΌαααααααααααα‘αΆα ααΆαααΎαααα αα·αααΆααααααααΆαααα α»α ααΆαα’αα»αααααα·ααΈααΆαααααααααΎααΆαα’ααααΆαα ααα»ααααααααΌααααα·ααΈααΆα ααΆααα·αααααΆα’αααΈαααααα·ααααΆαααααΆααααααΎαααΆααααα ααααααααΆα ααΆααααααΎαααΆααααααΆαα αα·αααΆααααααααααααΆαα’ααααα αα½αααα αααΆαααααααΆααα’αααα
αααααααααΆααααα αΆααααα·ααΈααΆαα ααα αΆααααα’αΆα αα»αα α·αααααΆαααΊααΉαααΆα αα·αα’αΆα ααααααααΆααααααααααΆααααΎααααΈαααααααΆααααααΌαααΆααααααΆααααααααΈαα»αα ααα»αααααααα»αα ααααααααααΆααΆαα’αα»αααααααααΆααα·αααααΆα’αΆα ααααΌαααΆααααααα’α ααΆα§ααΆα ααα ααΎααααΈαααααΎαααΆααααααΌααααα αα·αααααΆααααααΌααααααααΆαααααααΆααααα ααααααΆαααΌα ααΆαααα’α½α αα’α·α αα·α RTT α’αΆα ααααΌαααΆααααααααα αα·ααΈααΆα ααΆααααΉαααΆαααααααααααααααααα»αααΆαα’αα»ααααααααααΆααααααΆααααααα MTU αααΆαααααΆααααΆααααααΆαα (ααα»ααααααααα·αααΎααΆαααααααΌαααΆαααααΎ) .
ααΌαα’ααα»αα ααααααΆαααα α·ααααα»αααΆααααααα’ααα αααα»ααααααΉααααα αΆαααα·ααααα αα·ααααααααααα’αααα
PS αααααΆααβα’αααβαααβα
αΆααβα’αΆααααααβαααα’α·αβα¬βααααΆααβααβα
ααβααΆαααααβαα·ααΈααΆαβ, αααβαα
βααΆααβααααααβαα
βααΎ GitHubeβ:
αααααααΆαα αα·αα’αααααααΆααααααααα
- αααααααα
αα
ααααααααα·ααΈααΆα TCPα
ααΆααΆααΆα’ααααααα ΠΈαα βαααα»αβααααααβαα»αααααΈ - ααΆαααααααα·ααΈααΆα UDPα
ααΆααΆααΆα’ααααααα ΠΈαα βαααα»αβααααααβαα»αααααΈ - ααΆααα·ααΆααααΆα’αααΈαα·ααΈααΆα RUDPα
draft-ietf-sigtran-reliable-udp-00 - αα·ααΈααΆααα·αααααααααα’αΆα
αα»αα
α·αααααΆαα
rfc α‘α‘α’α£ ΠΈrfc α‘α‘α’α£ - ααΆαα’αα»ααααααΆααααααααΆααααααΆααααΆαα
ααα
αΆαααΎ UDPα
αααααααααααα»ααααααααΆαααααα’αααααΆαα½α .NET αα·α UDP - α’ααααααα·αααααΆα’αααΈααααααΆαααααααΆαα NATα
ααΆαααααΆαααααααΆααααααΈαα·ααααααααα·ααααααΆααααααΆαα’αααααααααα’αΆααααααΆα - ααΆαα’αα»ααααααααΌαααααα·ααΈα’ααααΆαα
ααΆαα’αα»αααα CLR Asynchronous Programming Model ΠΈααααα’αα»ααααααααΌαα ααΆ IAsyncResult - ααΆααααααΌαααααΌαααααα·ααΈα’ααααΆααα
ααααΆαα’ααααΆαααα’ααααΎααΆααα·α
αα
(APM αααα»α TAP)α
αααααα·ααΈ TPL αα·ααααααααΈ .NET Asynchronous Programming
α’ααααααααααΆαα½αααααΆα αα·αααααααα’ααααΆαααααααααα
αα
αα
α»ααααααααΆαα ααΌαα’ααα»α
ααααα: www.habr.com