Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

Ua leva ona suia le Initaneti. O se tasi o fesoʻotaʻiga Initaneti autu, UDP e faʻaaogaina e talosaga e le gata e tuʻuina atu faʻamaumauga ma faʻasalalauga, ae faʻapea foʻi ona tuʻuina atu fesoʻotaʻiga a tupulaga i le va o nodes fesoʻotaiga. Ona o lona mamanu faigofie, o lenei faʻasalalauga e tele faʻaoga e leʻi fuafuaina muamua; ae ui i lea, o faʻaletonu o le faʻasalalauga, e pei o le leai o se faʻamautinoaga tuʻuina atu, e leʻi mou atu. O lenei tusiga o loʻo faʻamatalaina se faʻatinoga o le Guaranteed Delivery Protocol over UDP.
Faʻamatalaga:ulufalega
Manaoga fa'akomepiuta
Ulutala UDP faatuatuaina
O mataupu faavae lautele o le protocol
Taimi fa'akomepiuta ma taimi
Fa'atuatuaina UDP Transmission State Diagram
loloto i totonu o le code. Vaega e pulea le felauaiga
loloto i totonu o le code. Setete

loloto i totonu o le code. Fausia ma fa'atuina feso'ota'iga
loloto i totonu o le code. Tapuni se feso'ota'iga ona ua uma le taimi
loloto i totonu o le code. Toe fa'aleleia o fa'amatalaga
Fa'atuatuaina UDP API
iʻuga
So'oga aoga ma tala

ulufalega

O le ata muamua o le Initaneti na vaʻaia ai se avanoa tuatusi laugatasi lea e tofu ai le pona ma se tuatusi IP faʻavaomalo ma tulaga ese ma e mafai ona fesoʻotaʻi saʻo ma isi pona. O le taimi nei o le Initaneti, o le mea moni, e ese le fausaga - tasi le vaega o tuatusi IP lalolagi ma le tele o vaega o loʻo i ai tuatusi tumaoti o loʻo natia i tua o masini NAT.I lenei fausaga, e na'o masini i totonu o le lalolagi avanoa avanoa e faigofie ona feso'ota'i ma so'o se tasi i luga o le feso'ota'iga ona o lo'o iai a latou tuatusi IP fa'apitoa, fa'asalalau i le lalolagi atoa. O se node o loʻo i luga o se fesoʻotaʻiga tumaoti e mafai ona faʻafesoʻotaʻi i isi nodes i luga o le fesoʻotaʻiga tutusa, faʻapea foʻi ma le faʻafesoʻotaʻi i isi, lauiloa lauiloa i le avanoa o le tuatusi lalolagi. O lenei feso'ota'iga e maua tele ona o le fa'aliliuga o tuatusi feso'otaiga. O masini NAT, e pei o le Wi-Fi routers, e faia ni fa'amatalaga fa'aliliuga fa'apitoa mo feso'ota'iga i fafo ma suia tuatusi IP ma numera o le taulaga i fa'aputu. Ole mea lea e fa'atagaina ai feso'ota'iga i fafo e faia mai se feso'ota'iga tuma'oti e talimalo ile avanoa ole tuatusi ole lalolagi. Ae i le taimi lava e tasi, o masini NAT e masani ona poloka uma feoaiga o loʻo oʻo mai seʻi vagana ua faʻatulaga tulafono eseese mo fesoʻotaʻiga o loʻo oʻo mai.

O lenei fausaga Initaneti ua lava le sa'o mo fegalegaleaiga a le tagata-server, pe a mafai ona maua tagata i luga o fesoʻotaʻiga tumaoti, ma o loʻo i ai i le 'auʻaunaga se tuatusi faʻavaomalo. Ae fa'atupu faigata mo le fa'afeso'ota'i sa'o o pona e lua i le va eseese feso'ota'iga tuma'oti. O feso'ota'iga tuusa'o o pona e lua e taua tele mo talosaga a tupulaga-i-peer e pei o felauaiga leo (Skype), avanoa komepiuta mamao (TeamViewer), po'o taaloga i luga ole laiga.

O se tasi o auala sili ona aoga mo le faʻavaeina o fesoʻotaʻiga a tupulaga i le va o masini o loʻo i luga o fesoʻotaʻiga tumaoti eseese e taʻua o le "puʻu". O lenei metotia e masani ona faʻaaogaina i talosaga e faʻavae i luga o le UDP protocol.

Ae afai o lau talosaga e manaʻomia le faʻamaoniaina o faʻamatalaga, mo se faʻataʻitaʻiga, e te fesiitai faila i le va o komepiuta, ona faʻaaogaina lea o le UDP o le a tele ni faʻafitauli ona o le mea moni o le UDP e le o se faʻasalalauga faʻamaonia ma e le faʻamautinoa le tuʻuina atu o pepa i le faasologa, e le pei le TCP protocol.

I lenei tulaga, ina ia mautinoa le tuʻuina atu o paʻu, e manaʻomia le faʻatinoina o se faʻataʻitaʻiga tulaga faʻaoga e maua ai le faʻatinoga talafeagai ma galue i luga o le UDP.

Ou te fia matauina i le taimi lava lena o loʻo i ai se TCP hole punching technique mo le faʻavaeina o fesoʻotaʻiga TCP i le va o nodes i luga o fesoʻotaʻiga tumaoti eseese, ae ona o le le lava o le lagolago mo le tele o masini NAT, e masani ona le manatu o le auala autu o le. fa'afeso'ota'i ia pona.

Mulimuli ane i lenei tusiga o le a naʻo le faʻatinoina o le faʻamaonia o le tuʻuina atu o faʻasalalauga. O le faʻatinoga o le UDP hole punching technique o le a faʻamatalaina i tala o loʻo mulimuli mai.

Manaoga fa'akomepiuta

  1. Fa'atuatuaina le tu'uina atu o pepa fa'atino e ala i se faiga fa'aalia lelei (e ta'ua o le fa'ailoa lelei)
  2. Le manaʻomia mo le faʻaleleia lelei o faʻamatalaga tetele, i.e. e tatau i le protocol ona aloese mai le toe lafoina o pusa e le mana'omia
  3. E tatau ona mafai ona faʻamalo le faiga o faʻamaoniga o le tuʻuina atu (le mafai ona galue o se "mama" UDP protocol)
  4. Avanoa o le faʻatinoina o le faʻatonuga, faʻatasi ai ma faʻamaoniga o feʻau taʻitasi
  5. Ole iunite fa'avae ole fa'asalalauina o fa'amatalaga i lalo ole protocol e tatau ona avea ma fe'au

O nei mana'oga e tele lava ina fetaui ma mana'oga mo le Fa'atuatuaina Fa'amaumauga Fa'amaumauga o lo'o fa'amatalaina i totonu RFC 908 и RFC 1151, ma sa ou faalagolago i nei tulaga faatonuina e atiina ae ai lenei feagaiga.

Ina ia malamalama i nei manaʻoga, seʻi o tatou vaʻavaʻai i faʻasologa o taimi o le faʻaliliuina o faʻamatalaga i le va o laina fesoʻotaʻiga e lua e faʻaaoga ai TCP ma UDP protocols. Se'i tatou leiloa se pepa e tasi i tulaga uma e lua.
Tuuina atu o faʻamatalaga e le o fesoʻotaʻi i luga ole TCP:Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

E pei ona mafai ona e vaʻai i le ata, i le tulaga o le paʻu leiloa, TCP o le a iloa le mea na leiloa ma lipoti atu i le tagata e auina atu e ala i le talosagaina o le numera o le vaega leiloa.
Fa'aliliuina fa'amatalaga e ala ile UDP protocol:Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

E le faia e le UDP ni laasaga e iloa ai mea leiloa. O le fa'atonutonuina o fa'amatalaga sese i le UDP protocol o le matafaioi atoa lea a le talosaga.

E maua se mea sese i le TCP protocol e ala i le faʻatuina o se fesoʻotaʻiga ma se node pito, teuina le tulaga o lenei fesoʻotaʻiga, faʻaalia le numera o bytes lafo i ulutala taʻitasi, ma le logoina o lisiti e faʻaaoga ai se numera faʻamaonia.

E le gata i lea, ina ia faʻaleleia le faʻatinoga (e pei o le auina atu o le sili atu ma le tasi le vaega e aunoa ma le mauaina o se faʻamaoniga), o le TCP protocol e faʻaaogaina se faʻamalama faʻasalalau - o le numera o bytes o faʻamatalaga o loʻo faʻamoemoe e maua e le tagata e auina atu le vaega.

E mafai ona maua nisi fa'amatalaga e uiga i le TCP protocol i totonu RFC 793, ma le UDP i totonu RFC 768, o fea latou te i ai, o le mea moni, ua faamatalaina.

Mai le mea o loʻo i luga, e manino lava ina ia mafai ona fatuina se faʻasalalauga faʻasalalauga faʻamaonia i luga o le UDP (o le a matou valaʻau mulimuli ane UDP fa'alagolago), e mana'omia le fa'atinoina o faiga fa'aliliuga fa'atusa e pei o le TCP. Fa'aigoa:

  • fa'asaoina tulaga feso'ota'iga
  • fa'aaoga numera vaega
  • fa'aaoga afifi fa'amaonia fa'apitoa
  • fa'aoga se fa'amalama fa'amalama fa'afaigofie e fa'atuputeleina ai le fa'aogaina o le protocol

E le gata i lea, e manaʻomia:

  • fa'ailoga le amataga o se fe'au e fa'asoa ai punaoa mo le feso'ota'iga
  • fa'ailo le fa'ai'uga o se fe'au, ia pasi atu le fe'au na maua i se talosaga i luga ma fa'asa'oloto punaoa fa'akomepiuta
  • fa'ataga se feso'ota'iga fa'apitoa fa'apitoa e fa'agata ai le tu'uina atu o le fa'ailoga e galue e pei o le "mama" UDP

Ulutala UDP faatuatuaina

Manatua o le UDP datagram o loʻo faʻapipiʻiina i totonu ole IP datagram. O le pusa UDP Fa'atuatuaina e fa'atatau i le "afifi" i se fa'amaumauga UDP.
Fa'alagolago i le fa'auluuluga UDP:Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

O le Fa'atuatuaina UDP fa'auluulu fausaga e fai si faigofie:

Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

  • Fu'a - fu'a pulea afifi
  • MessageType - ituaiga feʻau, faʻaaogaina e talosaga i luga e lesitala ai i feʻau faʻapitoa
  • TransmissionId - numera faʻasalalau, faʻatasi ai ma le tuatusi ma le taulaga a le tagata e mauaina, faʻamaonia tulaga ese le fesoʻotaʻiga
  • PacketNumber – numera afifi
  • Filifiliga – filifiliga fa'aopoopo fa'akomepiuta. I le tulaga o le pepa muamua, e faʻaaogaina e faʻaalia ai le tele o feʻau

O fu'a e fa'apea:

  • FirstPacket - o le pepa muamua o le feʻau
  • NoAsk - e le manaʻomia e le feʻau le faiga faʻamaonia e mafai ai
  • LastPacket - pepa savali mulimuli
  • RequestForPacket - pepa fa'amaonia po'o se talosaga mo se mea na leiloa

O mataupu faavae lautele o le protocol

Talu ai o loʻo taulaʻi le Faʻatuatuaina UDP i le faʻamautinoaina o le tuʻuina atu o se feʻau i le va o nodes e lua, e tatau ona mafai ona faʻatuina se fesoʻotaʻiga ma le isi itu. Ina ia faʻatuina se fesoʻotaʻiga, e tuʻuina atu e le itu e auina atu se afifi ma le FirstPacket fuʻa, o le tali o lona uiga o le fesoʻotaʻiga ua faʻavaeina. O pepa tali uma, po'o, i se isi faaupuga, pepa fa'ailoa, e fa'atulaga i taimi uma le tau o le PacketNumber fanua i le tasi e sili atu nai lo le PacketNumber sili ona taua o pepa na taunu'u manuia. O le avanoa o Filifiliga mo le pepa muamua na lafoina e faʻamaumau ai le tele o feʻau.

E fa'aogaina se masini fa'apena e fa'amae'a ai le feso'ota'iga. O le fu'a LastPacket o lo'o fa'atulaga i le taga fe'au mulimuli. O le pepa tali e faʻaalia ai le numera o le pusa mulimuli + 1, lea mo le itu e mauaina o lona uiga o le tuʻuina atu o le feʻau manuia.
Ata o le fa'avaeina ma le fa'amutaina o feso'ota'iga:Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

A faʻamautu le fesoʻotaʻiga, e amata le faʻaliliuina o faʻamatalaga. O faʻamatalaga e tuʻuina atu i poloka o afifi. O poloka ta'itasi, se'i vagana le mea mulimuli, o lo'o i ai se numera fa'amautu o pepa. E tutusa ma le tele o le mauaina / faʻasalalau faamalama. Ole poloka fa'amaumauga mulimuli atonu e itiiti ni afifi. A maeʻa ona tuʻuina atu poloka taʻitasi, o loʻo faʻatali le itu e auina atu mo le faʻamaoniga o le tuʻuina atu, poʻo se talosaga mo le toe tuʻuina atu o pepa na leiloa, ma tuʻu ai le avanoa e maua / faʻasalalau e tatala e maua ai tali. A maeʻa ona maua le faʻamaoniga o le tuʻuina atu o poloka, o le faʻamalama faʻafeiloaʻi / felauaiga e sui ma o le isi poloka o faʻamatalaga e lafoina.

O le itu e taliaina na te mauaina ia afifi. E siaki pepa ta'itasi pe pa'u i totonu o le fa'amalama fa'asalalau. O afifi ma kopi e le pa'u i totonu o le faamalama e faʻaumatia. Aua Talu ai ona o le tele o le faʻamalama e faʻamautu ma tutusa mo le tagata e mauaina ma le tagata e auina atu, ona i ai lea i le tulaga o le tuʻuina atu o se poloka o paʻu e aunoa ma se leiloa, o le faʻamalama o loʻo suia e maua ai pusa o le isi poloka faʻamaumauga ma tuʻuina atu se faʻamaoniga. . Afai e le fa'atumuina le fa'amalama i totonu o le vaitaimi na fa'atulaga e le taimi faigaluega, o le a fa'alauiloa se siaki e va'ai po'o fea afifi e le'i tu'uina atu ma o le a tu'uina atu talosaga mo le toe lafo.
Toe fa'aliliuina ata:Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

Taimi fa'akomepiuta ma taimi

E tele mafua'aga e le mafai ai ona fa'amauina se so'oga. Mo se faʻataʻitaʻiga, pe afai o le pati o loʻo mauaina e leai se initaneti. I lenei tulaga, pe a taumafai e faʻatūina se fesoʻotaʻiga, o le a tapunia le fesoʻotaʻiga ona o se taimi malolo. O le fa'atinoga o le UDP Fa'atuatuaina e fa'aogaina ai taimi e lua e fa'atulaga ai taimi fa'agata. O le mea muamua, o le taimi faigaluega, e faʻaaogaina e faʻatali mo se tali mai le talimalo mamao. Afai e fa'aosoina i le itu o lo'o tu'uina atu, ona toe fa'afo'i lea o le pepa mulimuli na lafo. Afai o le taimi e faʻaosoina i le tagata e mauaina, ona faia lea o se siaki mo pepa leiloa ma talosaga mo le toe tuʻuina atu e lafo.

O le taimi lona lua e manaʻomia e tapunia ai le fesoʻotaʻiga pe a leai se fesoʻotaʻiga i le va o nodes. Mo le itu e auina atu, e amata vave lava pe a uma le taimi faigaluega, ma faʻatali mo se tali mai le node mamao. Afai e leai se tali i totonu o le vaitaimi faʻamaonia, e faʻamutaina le fesoʻotaʻiga ma faʻasaʻoloto punaoa. Mo le itu e mauaina, e amata le taimi tapunia o feso'ota'iga pe a uma ona mu fa'alua le taimi faigaluega. E mana'omia lenei mea e fa'amautinoa ai le leiloa o le pepa fa'ailoa. Pe a mu le taimi, e faamutaina foi le sootaga ma tatala punaoa.

Fa'atuatuaina UDP Transmission State Diagram

O ta'iala fa'agaioiga o le protocol e fa'atinoina i totonu o se masini fa'agata, o setete ta'itasi e nafa ma se fa'atonuga o le fa'aogaina o pusa.
Fa'atuatuaina le fa'afanua o le setete o le UDP:

Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

punitia - e le o se setete, o le amataga ma le faʻaiʻuga mo le masini. Mo le setete punitia e maua se poloka faʻatonutonu faʻasalalau, lea, faʻaaogaina se UDP server asynchronous, toe faʻafeiloaʻi paʻu i fesoʻotaʻiga talafeagai ma amata ai le gaioiga o le setete.

FirstPacketSending – o le tulaga muamua lea o lo'o iai le feso'ota'iga i fafo pe a lafo se fe'au.

I lenei setete, o le pepa muamua mo feʻau masani e lafoina. Mo feʻau e aunoa ma se faʻamaoniga o le auina atu, naʻo le pau lea o le setete - o le feʻau atoa o loʻo lafoina i totonu.

SendingCycle – tulaga fa'avae mo le fa'asalalauina o fa'amatalaga fe'au.

Suiga i ai mai le setete FirstPacketSending faia ina ua uma ona auina atu le pepa savali muamua. O le tulaga lea e o'o mai uma ai fa'aaliga ma talosaga mo le toe fa'asalalau. O le alu ese mai ai e mafai i ni tulaga se lua - i le tulaga e manuia ai le tuʻuina atu o le feʻau pe ona o se taimi malolo.

FirstPacketReceived – tulaga muamua mo le tagata e mauaina le fe'au.

E siakiina le saʻo o le amataga o le faʻasalalauga, fatuina fausaga talafeagai, ma tuʻuina atu se faʻamaoniga o le mauaina o le pepa muamua.

Mo se feʻau o loʻo i ai se pusa e tasi ma lafo e aunoa ma le faʻaogaina o se faʻamaoniga o le tuʻuina atu, naʻo le pau lea o le setete. A maeʻa ona faʻagasolo sea feʻau, ua tapunia le fesoʻotaʻiga.

Faʻapotopotoga – tulaga fa'avae mo le mauaina o fa'amatalaga fe'au.

Na te tusia pepa i le teuina le tumau, siaki mo le leiloa o pepa, auina atu faʻamaoniga o le tuʻuina atu o se poloka o taga ma le feʻau atoa, ma auina atu talosaga mo le toe lafoina o pepa na leiloa. Afai e maua lelei le savali atoa, e alu le feso'ota'iga i le Maea, a leai e tupu se taimi e alu ese ai.

Maea – tapunia le feso'ota'iga pe a maua lelei le fe'au atoa.

O lenei setete e manaʻomia mo le faʻapotopotoina o feʻau ma mo le tulaga na leiloa ai le faʻamaoniga o le tuʻuina atu o feʻau i luga o le ala i le na auina atu. O lenei setete e alu ese i se taimi malolo, ae o le fesoʻotaʻiga ua manatu ua tapunia manuia.

loloto i totonu o le code. Vaega e pulea le felauaiga

O se tasi o elemene autu o le Faʻatuatuaina UDP o le poloka faʻatonutonu faʻasalalau. O le faʻamoemoega o lenei poloka o le teuina o fesoʻotaʻiga o loʻo i ai nei ma elemene ausilali, faʻasoa pepa o loʻo oʻo mai i fesoʻotaʻiga talafeagai, tuʻuina atu se atinaʻe mo le lafoina o paʻu i le fesoʻotaʻiga, ma faʻatino le protocol API. O le poloka faʻatonutonu faʻasalalau e maua ai faʻamaumauga mai le UDP layer ma toe faʻafeiloaʻi i le masini a le setete mo le gaosiga. Mo le mauaina o pepa, e faʻaaogaina se UDP server asynchronous.
O nisi sui o le vasega 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;    	
  //...
}

Fa'atinoina o se 'au'aunaga UDP e le fa'atasi:

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);
}

Mo fe'au fe'au ta'itasi, e faia se fausaga e iai fa'amatalaga feso'ota'iga. Ua ta'ua lea fausaga faamaumauga o fesootaiga.
O nisi sui o le vasega 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;
  //...
}

loloto i totonu o le code. Setete

O lo'o fa'atinoina e Setete le masini a le setete o le Reliable UDP protocol, lea e tupu ai le fa'agaioiga autu o fa'aputu. O le vasega faʻapitoa ReliableUdpState e maua ai se atinaʻe mo le setete:

Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

O le faʻatonuga atoa o le protocol e faʻatinoina e vasega o loʻo tuʻuina atu i luga, faʻatasi ai ma se vasega ausilali e tuʻuina atu auala faʻapitoa, e pei o, mo se faʻataʻitaʻiga, fausia le ReliableUdp header mai le faʻamaumauga fesoʻotaʻiga.

Le isi, o le a tatou iloiloina auiliili le faʻatinoga o auala faʻaoga e faʻamalamalamaina ai algorithms faavae o le protocol.

DisposeByTimeout auala

Ole auala DisposeByTimeout e nafa ma le tuʻuina atu o punaoa fesoʻotaʻiga pe a maeʻa le taimi faʻagata ma mo le faʻailoga manuia/toilalo o le faʻasalalauina o feʻau.
ReliableUdpState.DisposeByTimeout:

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

E na'o le fa'asili i le setete Maea.
Maea.DisposeByTimeout:

protected override void DisposeByTimeout(object record)
{
  ReliableUdpConnectionRecord connectionRecord = (ReliableUdpConnectionRecord) record;
  // сообщаем об успешном получении сообщения
  SetAsCompleted(connectionRecord);        
}

ProcessPackets auala

O le ProcessPackets auala e nafa ma le faʻaopoopoina o gaioiga o le afifi poʻo afifi. Vala'au sa'o pe ala mai i le taimi fa'atali o le pepa.

mafai Faʻapotopotoga o le auala ua soloia ma e nafa ma le siakiina o pepa leiloa ma le suiga i le setete Maea, i le tulaga o le mauaina o le pepa mulimuli ma pasi lelei le siaki
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);
  }
}

mafai SendingCycle ua valaauina lenei metotia i luga o se taimi, ma e nafa ma le toe auina atu o le savali mulimuli, faapea foi ma le amataina o le sootaga tapunia taimi.
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);
}

mafai Maea O le auala e taofi ai le taimi fa'asolosolo ma fa'asalalau atu se fe'au i le au fai saofaga.
Maea.ProcessPackets:

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  if (connectionRecord.WaitForPacketsTimer != null)
    connectionRecord.WaitForPacketsTimer.Dispose();
  // собираем сообщение и передаем его подписчикам
  ReliableUdpStateTools.CreateMessageFromMemoryStream(connectionRecord);
}

ReceivePacket auala

mafai FirstPacketReceived O le galuega autu o le auala o le fuafuaina lea pe na taunuu moni mai le pepa savali muamua i luga o le atinaʻe, ma ia faʻapipiʻi foʻi se feʻau e aofia ai se pepa e tasi.
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);
  }
}

mafai SendingCycle ua fa'asili lenei auala e talia fa'amaoniga tilivaina ma talosaga toe fa'asalalau.
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));
}

mafai Faʻapotopotoga i le ReceivePacket method, o le galuega autu o le faʻapipiʻiina o le feʻau mai faʻailoga o loʻo oʻo mai e tupu.
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);
  }
}

mafai Maea Pau lava le galuega o le auala o le auina atu lea o se faʻamaoniga faifaipea o le faʻafeiloaʻi manuia o le feʻau.
Maea. MauaPacket:

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // повторная отправка последнего пакета в связи с тем,
  // что последний ack не дошел до отправителя
  if (header.Flags.HasFlag(ReliableUdpHeaderFlags.LastPacket))
  {
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
  }
}

SendPacket auala

mafai FirstPacketSending O lenei metotia e auina atu ai le pepa muamua o faʻamatalaga, pe, afai e le manaʻomia e le feʻau le faʻamaoniga o le tuʻuina atu, o le savali atoa.
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);
}

mafai SendingCycle i lenei auala, e auina atu se poloka o afifi.
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 );
  }
}

loloto i totonu o le code. Fausia ma fa'atuina feso'ota'iga

I le taimi nei ua tatou masani i setete masani ma metotia faʻaaogaina e faʻatautaia ai setete, e mafai ona tatou vaʻavaʻai atili i nisi faʻataʻitaʻiga o le faʻaogaina o le protocol.
Fa'asologa o fa'amatalaga i lalo o tulaga masani:Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

Sei o tatou tilotilo totoa i le foafoaga faamaumauga o fesootaiga e fa'afeso'ota'i ma lafo le pepa muamua. O le fesiitaiga e masani lava ona amataina e le talosaga e taʻua le auala API mo le lafoina o le feʻau. O le isi, o le auala StartTransmission o le poloka pule faʻasalalau e faʻaaogaina, amata faʻasalalau faʻamatalaga mo le feʻau fou.
Fausia se feso'ota'iga i fafo:

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]);
}

Tuuina atu o le pepa muamua (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);
}

A maeʻa ona tuʻuina atu le pepa muamua, e ulufale le tagata e auina atu i le setete SendingCycle – fa'atali mo le fa'amaoniga o le tu'uina atu o afifi.
O le itu e maua ai, e fa'aaoga ai le EndReceive method, talia le pepa lafo ma fai se mea fou faamaumauga o fesootaiga ma pasi lenei afifi, faatasi ai ma se ulutala ua uma ona saunia, i le setete ReceivePacket metotia mo le gaosiga FirstPacketReceived
Fausia se feso'ota'iga i le itu e maua ai:

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);
}

Mauaina o le pepa muamua ma auina atu se fa'ailoga (FirstPacketReceived state):

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);
  }
}

loloto i totonu o le code. Tapuni se feso'ota'iga ona ua uma le taimi

O le fa'afoeina o taimi fa'agata ose vaega taua ole UDP Fa'atuatuaina. Mafaufau i se faʻataʻitaʻiga ua le manuia ai se node ogatotonu ma le tuʻuina atu o faʻamatalaga i itu uma e lua ua le mafai.
Ata o le tapunia o se feso'ota'iga i le taimi fa'agata:Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

E pei ona vaaia i le ata, o le taimi galue a le tagata e auina atu e amata vave lava pe a uma ona lafo se poloka o pepa. E tupu lenei mea i le auala SendPacket a le setete SendingCycle.
Fa'aagaaga le taimi galue (sendingCycle state):

public override void SendPacket(ReliableUdpConnectionRecord connectionRecord)
{      
  // отправляем блок пакетов   
  // ...   
  // перезапускаем таймер после отправки
  connectionRecord.WaitForPacketsTimer.Change( connectionRecord.ShortTimerPeriod, -1 );
  if ( connectionRecord.CloseWaitTimer != null )
    connectionRecord.CloseWaitTimer.Change( -1, -1 );
}

E fa'atulaga taimi ole taimi pe a fai le feso'ota'iga. E le mafai, ShortTimerPeriod e 5 sekone. I le faʻataʻitaʻiga ua seti i le 1,5 sekone.

Mo se fesoʻotaʻiga o loʻo oʻo mai, e amata le taimi pe a uma ona maua le faʻamaumauga mulimuli na maua; e tupu lenei mea i le ReceivePacket auala a le setete Faʻapotopotoga
Fa'aagaaga le taimi galue (Tulaga fa'aopoopo):

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);
  // ...
}

O le feso'ota'iga o lo'o sau e le'i mauaina nisi fa'aputu i le taimi fa'atali mo le taimi faigaluega. Na ta le taimi ma taʻua le ProcessPackets method, lea na iloa ai pepa na leiloa ma auina atu talosaga toe lafo mo le taimi muamua.
Auina atu talosaga toe lafo (Tulaga fa'aopoopo):

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);
  }
}

Ua seti le fesuiaiga TimerSecondTry i moni. O lenei fesuiaiga e nafa ma le toe amataina o le taimi faigaluega.

I le itu a le tagata e auina atu, e fa'aosoina fo'i se taimi galue ma o le pepa mulimuli na lafo atu e toe fa'afo'i.
Fa'aagaoi le taimi tapuni feso'ota'iga (sendingCycle state):

public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
{
  // ...        
  // отправляем повторно последний пакет 
  // ...        
  // включаем таймер CloseWait – для ожидания восстановления соединения или его завершения
  StartCloseWaitTimer(connectionRecord);
}

A maeʻa lena, e amata le taimi tapunia fesoʻotaʻiga i le fesoʻotaʻiga i fafo.
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);
}

Ole taimi fa'aletonu ole taimi ole feso'ota'iga e 30 sekone.

A maeʻa sina taimi puʻupuʻu, e toe faʻaosoina le taimi galue i le itu e mauaina, toe tuʻuina atu talosaga, a maeʻa ona amata le taimi tapuni mo le fesoʻotaʻiga ulufale.

Pe a mu le taimi tapuni, e tatala uma punaoa o faamaumauga uma e lua. Ua lipotia e le tagata na auina atu le le manuia o le tilivaina i le talosaga i luga (tagai API Fa'atuatuaina UDP).
Tu'uina atu punaoa fa'amaumauga feso'ota'iga:

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);
  }
}

loloto i totonu o le code. Toe fa'aleleia o fa'amatalaga

Ata o le toe fa'aleleia o fa'amatalaga pe a leiloa le pepa:Fa'atinoga o le Fa'atuatuaina Udp protocol mo .Net

E pei ona uma ona talanoaina i le tapunia o se fesoʻotaʻiga e ala i le faʻagata, pe a maeʻa le taimi faigaluega, o le a siaki e le tagata faʻapipiʻi pepa na leiloa. Afai o lo'o leiloa pepa, o le a tu'ufa'atasia se lisi o numera o pepa e le'i o'o atu i le tagata na mauaina. O nei numera o loʻo tuʻuina i totonu o le LostPackets array o se fesoʻotaʻiga faʻapitoa ma talosaga mo le toe tuʻuina atu e lafo.
Tuuina atu o talosaga e toe momoli atu afifi (Tulaga fa'aopoopo):

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);
      }
    }
    // ...
  }
}

O le a talia e le tagata e auina atu le talosaga toe lafo ma toe lafo atu afifi o loo misi. E taua le matauina o le taimi nei ua uma ona amataina e le tagata auina atu se taimi tapunia o fesoʻotaʻiga ma, i le mauaina o se talosaga, ua toe setiina.
Toe lafo atu pepa leiloa (SendingCycle state):

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));
}

O le pepa fa'atiga (packet #3 i le ata) e maua e le feso'ota'iga o lo'o sau. E faia se siaki ina ia mautinoa o loʻo tumu le faamalama o le mauaina ma toe faʻaleleia le faʻasalalauga masani.
Siaki mo mea na maua i le faamalama o le mauaina (Tulaga o le Assembling):

public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header, byte[] payload)
{
  // ...
  // увеличиваем счетчик пакетов        
  connectionRecord.PacketCounter++;
  // записываем в массив управления окном текущий номер пакета        
  connectionRecord.WindowControlArray[header.PacketNumber - connectionRecord.WindowLowerBound] = header.PacketNumber;
  // устанавливаем наибольший пришедший пакет        
  if (header.PacketNumber > connectionRecord.RcvCurrent)
    connectionRecord.RcvCurrent = header.PacketNumber;
  // перезапускам таймеры        
  connectionRecord.TimerSecondTry = false;
  connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
  if (connectionRecord.CloseWaitTimer != null)
    connectionRecord.CloseWaitTimer.Change(-1, -1);
  // ...
  // если нам пришли все пакеты окна, то сбрасываем счетчик
  // и высылаем пакет подтверждение
  else if (connectionRecord.PacketCounter == connectionRecord.WindowSize)
  {
    // сбрасываем счетчик.      
    connectionRecord.PacketCounter = 0;
    // сдвинули окно передачи
    connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
    // обнуление массива управления передачей
    connectionRecord.WindowControlArray.Nullify();
    ReliableUdpStateTools.SendAcknowledgePacket(connectionRecord);
  }
  // ...
}

Fa'atuatuaina UDP API

Ina ia fegalegaleai ma le faʻasalalauga faʻasalalauga faʻamatalaga, o loʻo i ai se vasega tatala Faʻatuatuaina Udp, o se afifi i luga o le poloka pule faʻasalalau. O tagata sili nei ona taua o le vasega:

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()    
}

O le mauaina o fe'au e faia e ala i le lesitala. Tuuina atu le saini mo le auala e toe fo'i ai:

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

Savali:

public class ReliableUdpMessage
{
  // тип сообщения, простое перечисление
  public ReliableUdpMessageTypes Type { get; private set; }
  // данные сообщения
  public byte[] Body { get; private set; }
  // если установлено в true – механизм подтверждения доставки будет отключен
  // для передачи конкретного сообщения
  public bool NoAsk { get; private set; }
}

Ina ia lesitala i se ituaiga feʻau patino ma / poʻo se tagata e tuʻuina atu, lua faʻamaufaʻailoga e faʻaogaina: ReliableUdpMessageTypes messageType ma IPEndPoint ipEndPoint.

Ituaiga fe'au:

public enum ReliableUdpMessageTypes : short
{ 
  // Любое
  Any = 0,
  // Запрос к STUN server 
  StunRequest = 1,
  // Ответ от STUN server
  StunResponse = 2,
  // Передача файла
  FileTransfer =3,
  // ...
}

O le feʻau e lafoina faʻatasi; mo lenei faʻamoemoe, o loʻo faʻaaogaina e le protocol se faʻataʻitaʻiga polokalame asynchronous:

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

O le iʻuga o le lafoina o se feʻau o le a moni - pe a taunuʻu manuia le feʻau ma le sese - pe afai na tapunia le fesoʻotaʻiga ona o se taimi malolo:

public bool EndSendMessage(IAsyncResult asyncResult)

iʻuga

E tele mea e leʻi faʻamatalaina i totonu o le lautele o lenei tusiga. Faiga fa'amaopoopoina o filo, tuusaunoaga ma le fa'afoeina o mea sese, fa'atinoga o auala e lafo ai fe'au fa'atasi. Ae o le totonugalemu o le protocol, o se faʻamatalaga o le faʻaogaina mo le faʻaogaina o pusa, faʻavaeina o se fesoʻotaʻiga ma le faʻatulagaina o taimi, e tatau ona sili atu ona manino mo oe.

O le fa'ata'ita'iga fa'ata'ita'iga o le fa'ata'ita'iga fa'atuatuaina o le tu'uina atu e fai si malosi ma fetuutuuna'i, ma fa'amalieina mana'oga na fa'amatalaina muamua. Ae ou te fia faaopoopo atu e mafai ona faaleleia le faatinoga o loo faamatalaina. Mo se faʻataʻitaʻiga, ina ia faʻateleina le gaosiga ma suia faʻamalosi taimi taimi, e mafai ona e faʻaopoopoina masini e pei o le faʻamalama matala ma le RTT i le protocol; o le a aoga foi le faʻatinoina o se masini mo le fuafuaina o le MTU i le va o nodes fesoʻotaʻiga (ae naʻo le tulaga o le auina atu. fe'au tetele).

Faafetai mo lou gauai mai, ou te tulimatai atu i au faʻamatalaga ma faʻamatalaga.

PS Mo i latou e fiafia i faʻamatalaga pe naʻo le manaʻo e faʻataʻitaʻi le protocol, o le fesoʻotaʻiga lea i le poloketi ile GitHube:
Poloketi UDP Fa'atuatuaina

So'oga aoga ma tala

  1. TCP Protocol Fa'amatalaga: i le gagana Peretania и i le gagana Rusia
  2. UDP protocol fa'amatalaga: i le gagana Peretania и i le gagana Rusia
  3. Talanoaga o le RUDP protocol: draft-ietf-sigtran-reliable-udp-00
  4. Fa'atuatuaina Fa'amaumauga Protocol: RFC 908 и RFC 1151
  5. O se faʻatinoga faigofie o le faʻamaoniga o le tuʻuina atu i luga ole UDP: Ave le Pulea Atoa o lau Fesootaiga ma .NET ma UDP
  6. O se tusiga o loʻo faʻamatalaina auala mo le faʻatoʻilaloina o NATs: Feso'ota'iga Feso'ota'iga a Umea i Uiga Feso'ota'iga Fa'aliliu tuatusi
  7. Fa'atinoga o le fa'ata'ita'iga polokalame asynchronous: Fa'atinoina o le CLR Asynchronous Programming Model и Fa'afefea ona fa'atino le mamanu mamanu IAsyncResult
  8. Si'itia le fa'ata'ita'iga fa'apolokalame fa'aasynchronous i le fa'ata'ita'iga asynchronous fa'avae galuega (APM i le TAP):
    TPL ma Fa'aleaganu'u .NET Asynchronous Polokalama
    Feso'ota'i ma Isi Mamanu ma Ituaiga Asynchronous

Fa'afouga: Fa'afetai mayorovp и sidristij mo le manatu o le faʻaopoopoina o se galuega i le atinaʻe. E le afaina le feso'ota'iga a le faletusi ma faiga fa'aoga tuai, aua O le 4th framework e lagolagoina uma le XP ma le 2003 server.

puna: www.habr.com

Faaopoopo i ai se faamatalaga