Patikimo UDP Protokolo Įgyvendinimas: Garantuotas Duomenų Perdavimas Per UDP

Šiuolaikinis internetas smarkiai skiriasi nuo savo pradinės architektūros, kurioje kiekvienas tinklo mazgas turėjo unikalų ir visuotinai pasiekiamą IP adresą. Šiandieninė interneto struktūra apima tiek visuotinai pasiekiamą IP adresų erdvę, tiek daugybę privačių tinklų, kurių mazgai yra paslėpti už NAT (Network Address Translation) įrenginių. Tokia architektūra palengvina kliento-serverio komunikaciją, tačiau apsunkina tiesioginį dviejų mazgų, esančių skirtinguose privačiuose tinkluose, sujungimą. Tai ypač svarbu „peer-to-peer“ (lygiavertėms) programoms, tokioms kaip internetiniai žaidimai, balso ar vaizdo skambučiai, kur tiesioginis ryšys yra esminis.

Vienas iš efektyviausių būdų užmegzti tokį lygiavertį ryšį - „skylių perforavimo“ (hole punching) technika, dažnai įgyvendinama naudojant UDP (User Datagram Protocol) protokolą. Tačiau UDP protokolas, nors ir greitas bei paprastas, neteikia garantuoto duomenų pristatymo, tvarkingo paketų surinkimo ar klaidų aptikimo. Jei programai, pavyzdžiui, failų perdavimui, reikalingas patikimas duomenų pristatymas, vien tik UDP nepakanka. Tokiais atvejais būtina įdiegti taikomojo lygmens protokolą, kuris veiktų virš UDP ir užtikrintų reikiamą funkcionalumą. Šis straipsnis skirtas būtent tokio, patikimo UDP protokolo, įgyvendinimui.

UDP protokolo schema

UDP Protokolo Reikalavimai ir Trūkumai

UDP protokolas yra transportavimo sluoksnio protokolas, žinomas dėl savo paprastumo ir greičio. Jis veikia be ryšio, t.y., nereikia užmegzti formalaus ryšio tarp siuntėjo ir gavėjo prieš siunčiant duomenis. UDP teikia nuolatinį paketų grupavimą ir surinkimą, tačiau negarantuoja jų tvarkingo pristatymo ar netgi to, kad visi paketai pasieks gavėją. Trūkumai, tokie kaip garantuoto pristatymo nebuvimas, tvarkingo paketų surinkimo stoka ir duomenų vientisumo nepatikrinimas (išskyrus kontrolinę sumą), yra esminiai, kai reikalingas patikimas duomenų perdavimas.

Palyginimui, TCP (Transmission Control Protocol) yra ryšiu grįstas protokolas, kuris užtikrina duomenų pristatymą, tvarkingą jų surinkimą ir dublikatų pašalinimą. TCP naudoja sudėtingesnį mechanizmą, apimantį ryšio užmezgimą, sekos numerius, patvirtinimus ir perdavimo langą, siekiant garantuoti duomenų vientisumą ir patikimumą. Tačiau šie mechanizmai sukuria papildomą delsą, todėl TCP nėra tinkamas realaus laiko aplikacijoms, kur svarbiausias yra greitis.

Dėl šių UDP trūkumų, siekiant sukurti patikimą pranešimų siuntimo protokolą per UDP (toliau - Patikimas UDP), būtina įdiegti mechanizmus, panašius į TCP, bet pritaikytus UDP aplinkai:

  • Patikimas paketų pristatymas: Naudojant teigiamą grįžtamojo ryšio (positive acknowledgment) mechanizmą, t.y., siuntėjas gauna patvirtinimą apie sėkmingai gautus paketus.
  • Efektyvus didelių duomenų perdavimas: Protokolas turi vengti nereikalingo paketų perdavimo ir optimizuoti siuntimą.
  • Galimybė atšaukti pristatymo patvirtinimo mechanizmą: Leidžia protokolui veikti kaip „grynas“ UDP, kai patikimumas nėra prioritetas.
  • Komandų režimo įgyvendinimas: Galimybė reikalauti patvirtinimo kiekvienam pranešimui.
  • Pranešimas kaip pagrindinis duomenų perdavimo vienetas: Visi duomenys perduodami kaip atskiri pranešimai.

Šie reikalavimai iš esmės sutampa su Patikimų duomenų protokolo reikalavimais, aprašytais RFC 908 ir RFC 1151, ir buvo pagrindas kuriant šį protokolą.

Patikima UDP Antraštė

Patikimo UDP paketas yra „įvyniotas“ į UDP datagramą, kuri savo ruožtu yra įdėta į IP datagramą. Patikimos UDP antraštės struktūra yra gana paprasta ir apima šiuos laukus:

  • Flags (Vėliavos): Kontrolinės vėliavėlės, nurodančios paketo tipą ir jo vaidmenį.
    • FirstPacket: Nurodo, kad tai yra pirmoji žinutės dalis.
    • NoAsk: Nurodo, kad žinutei nereikia patvirtinimo.
    • LastPacket: Nurodo, kad tai yra paskutinis žinutės paketas.
    • RequestForPacket: Nurodo, kad tai yra patvirtinimo paketas arba prašymas dėl prarasto paketo.
  • MessageType (Pranešimo tipas): Naudojamas ankstesnėse programose konkretiems pranešimams užsiprenumeruoti.
  • TransmissionId (Siuntimo ID): Kartu su gavėjo adresu ir prievadu vienareikšmiškai identifikuoja ryšį.
  • PacketNumber (Paketo numeris): Sekos numeris, leidžiantis tvarkingai surinkti pranešimą.
  • Options (Parinktys): Papildomos protokolo parinktys. Pirmojo paketo atveju naudojamas pranešimo dydžiui nurodyti.

Patikimos UDP antraštės struktūra

Bendrieji Protokolo Principai

Patikimas UDP yra orientuotas į garantuotą pranešimų perdavimą tarp dviejų mazgų, todėl jis turi sugebėti užmegzti ir palaikyti ryšį.

Ryšio Užmezgimas ir Uždarymas

Ryšio užmezgimas prasideda siuntėjui išsiunčiant paketą su FirstPacket vėliava. Atsakymas į šį paketą signalizuoja, kad ryšys užmegztas. Visuose atsakymų (patvirtinimo) paketuose lauko PacketNumber reikšmė yra didesnė vienu už didžiausią sėkmingai gautą paketą. Pirmojo išsiųsto paketo Options lauke nurodomas visas pranešimo dydis.

Ryšio uždarymas vyksta panašiu principu. Paskutiniame pranešimo pakete nustatoma LastPacket vėliavėlė. Atsakymo pakete nurodomas paskutiniojo paketo numeris + 1, kas gavėjui signalizuoja apie sėkmingą pranešimo pristatymą.

Ryšio nustatymo ir užbaigimo schema

Duomenų Perdavimas ir Langų Mechanizmas

Užmezgus ryšį, prasideda duomenų perdavimas blokais. Kiekviename bloke, išskyrus paskutinį, yra nustatytas paketų skaičius, lygus priėmimo/perdavimo lango dydžiui. Paskutiniame bloke gali būti mažiau paketų. Po kiekvieno išsiųsto bloko siuntėjas laukia patvirtinimo arba prašymo pakartotinai pristatyti prarastus paketus, palikdamas atvirą priėmimo/perdavimo langą atsakymams gauti. Gavus bloko pristatymo patvirtinimą, langas pasislenka, ir siunčiamas kitas duomenų blokas.

Gavėjas priima paketus, tikrindamas, ar jie patenka į perdavimo langą. Paketai ir dublikatai, kurie nepatenka į langą, yra filtruojami. Jei lango dydis yra fiksuotas ir vienodas siuntėjui bei gavėjui, o paketas pristatomas be nuostolių, langas pasislenka prie kito duomenų bloko paketų, ir išsiunčiamas pristatymo patvirtinimas.

Jei langas nepasipildo per nustatytą laiką (veikiant laikmačiui), pradedamas tikrinti, kurie paketai nebuvo pristatyti, ir siunčiami prašymai pakartotinai juos pristatyti.

Retransliavimo schema

Laikmatis ir Protokolo Laikmačiai

Patikimas UDP naudoja kelis laikmačius, kad užtikrintų ryšio stabilumą ir išteklių valdymą:

  1. Darbo laikmatis (timeout timer): Naudojamas laukti atsakymo iš nuotolinio mazgo. Jei suveikia siuntėjo pusėje, paskutinis išsiųstas paketas siunčiamas iš naujo. Jei laikmatis suveikia gavėjo pusėje, tikrinama, ar nėra prarastų paketų, ir siunčiami pakartotinio pristatymo prašymai.
  2. Ryšio uždarymo laikmatis: Naudojamas ryšiui nutraukti, jei tarp mazgų nutrūksta ryšys. Siuntėjo pusėje jis paleidžiamas pasibaigus darbo laikmačiui ir laukia atsakymo. Jei per nustatytą laiką atsakymas negaunamas, ryšys nutraukiamas. Gavėjo pusėje šis laikmatis paleidžiamas du kartus pasibaigus darbo laikmačiui, siekiant apsidrausti nuo patvirtinimo paketo praradimo. Pasibaigus laikmačiui, ryšys taip pat nutraukiamas.

Šie laikmačiai yra kritiniai siekiant užtikrinti, kad sistema tinkamai reaguotų į tinklo problemas, tokias kaip priimančiojo mazgo nepasiekiamumas ar paketų praradimas.

Patikima UDP Perdavimo Būsenos Diagrama

Protokolo logika įgyvendinama baigtinių būsenų mašinoje, kur kiekviena būsena atsako už tam tikrą paketų apdorojimo logiką:

  • Uždaryta (Closed): Būsenos pradžia ir pabaiga. Iš čia gaunamas perdavimo valdymo blokas, kuris persiunčia paketus atitinkamoms jungtims ir pradeda būsenos apdorojimą.
  • FirstPacketSending (Pirmasis paketas siunčiamas): Išeinančio ryšio būsena, kai siunčiamas pranešimas. Siunčiamas pirmasis paprastų pranešimų paketas. Jei pranešimui nereikia patvirtinimo, tai vienintelė būsena, kai siunčiamas visas pranešimas.
  • SendingLoop (Siuntimo ciklas): Pagrindinė pranešimų paketų perdavimo būsena. Į ją pereinama po pirmojo paketo išsiuntimo. Čia gaunami visi patvirtinimai ir prašymai persiųsti. Iš jos išeinama arba sėkmingai pristacius pranešimą, arba pasibaigus laikui.
  • FirstPacketReceived (Pirmasis paketas gautas): Pranešimo gavėjo pradinė būsena. Tikrina perdavimo pradžios teisingumą, sukuria reikiamas struktūras ir siunčia patvirtinimą apie pirmojo paketo gavimą. Jei pranešimas susideda iš vieno paketo ir siunčiamas be patvirtinimo, tai yra vienintelė būsena.
  • Assembly (Surinkimas): Pagrindinė pranešimų paketų priėmimo būsena. Įrašo paketus į laikinosios saugyklos, tikrina, ar paketai neprarasti, siunčia patvirtinimus ir prašymus pakartotinai pristatyti prarastus paketus. Sėkmingai gavus visą pranešimą, pereinama į būseną Completed.
  • Completed (Užbaigta): Ryšio nutraukimas sėkmingai gavus visą pranešimą. Ši būsena reikalinga pranešimo surinkimui ir tuo atveju, kai siuntėjui buvo prarastas pranešimo pristatymo patvirtinimas. Iš jos baigiasi skirtasis laikas, tačiau ryšys laikomas sėkmingai uždarytu.

Patikimos UDP būsenos diagrama

Giliau į Kodą: Perdavimo Valdymo Blokas

Vienas iš pagrindinių Patikimo UDP elementų yra perdavimo valdymo blokas (Transmission Control Block - TCB). Jo užduotys apima:

  • Esamų ryšių ir pagalbinių elementų saugojimą.
  • Gaunamų paketų paskirstymą atitinkamoms jungtims.
  • Sąsajos paketų siuntimui į ryšį suteikimą.
  • Protokolo API įgyvendinimą.

Perdavimo valdymo blokas gauna paketus iš UDP sluoksnio ir persiunčia juos būsenos mašinai apdoroti. Norint gauti paketus, jis įdiegia asinchroninį UDP serverį. Kiekvienam pranešimo perdavimui sukuriama struktūra, vadinama ryšio įrašu, kurioje saugoma visa reikalinga informacija apie ryšį.

// Represents the state of a reliable UDP connection.public abstract class ReliableUdpState{ // Method to process incoming packets. public abstract void ProcessPackets(ConnectionRecord connection, DatagramPacket packet); // Method to handle timeouts. public abstract void DisposeByTimeout(ConnectionRecord connection); // Method to send packets. public abstract void SendPacket(ConnectionRecord connection, DatagramPacket packet); // Method to receive packets. public abstract DatagramPacket ReceivePacket(ConnectionRecord connection); // Method to handle sending packets. public abstract void HandleSending(ConnectionRecord connection); // Method to handle completion. public abstract void HandleCompleted(ConnectionRecord connection);}// Example of a specific state: Sending loop.public class SendingLoopState : ReliableUdpState{ // ... implementation details ...}

Giliau į Kodą: Būsenų Įgyvendinimas

Būsenų įgyvendinimas grindžiamas abstrakčia klase ReliableUdpState, kuri apibrėžia bendrą sąsają visoms būsenoms. Konkreti protokolo logika įgyvendinama paveldint šią klasę ir realizuojant jos metodus.

DisposeByTimeout Metodas

Šis metodas atsakingas už ryšio išteklių atleidimą pasibaigus skirtajam laikui ir signalizavimą apie sėkmingą/nesėkmingą pranešimų pristatymą. Jis nepaisomas tik Completed būsenoje.

ProcessPackets Metodas

Metodas ProcessPackets apdoroja papildomus paketus arba paketų blokus. Jis gali būti iškviečiamas tiesiogiai arba per paketo laukimo laikmatį. Assembly būsenoje šis metodas yra nepaisomas ir atsakingas už prarastų paketų patikrinimą bei perėjimą į Completed būseną.

ReceivePacket Metodas

  • FirstPacketReceived būsenoje pagrindinė užduotis yra nustatyti, ar pirmasis pranešimo paketas iš tikrųjų atkeliavo, ir surinkti vieno paketo pranešimą.
  • SendingLoop būsenoje šis metodas nepaisomas, kad būtų priimti pristatymo patvirtinimai ir pakartotinio siuntimo užklausos.
  • Assembly būsenoje, taikant ReceivePacket metodą, vyksta pagrindinis pranešimo surinkimo iš gaunamų paketų darbas.
  • Completed būsenoje vienintelė užduotis - išsiųsti pakartotinį sėkmingo pranešimo pristatymo patvirtinimą.

SendPacket Metodas

  • FirstPacketSending būsenoje šiuo metodu išsiunčiamas pirmasis duomenų paketas arba, jei pranešimui nereikia patvirtinimo, visas pranešimas.

Ryšių Kūrimas ir Užmezgimas

Kaip minėta anksčiau, ryšio užmezgimas ir palaikymas yra esminė Patikimo UDP dalis. Siuntėjas siunčia paketą su FirstPacket vėliava, o gavėjas, gavęs šį paketą, atpažįsta jį kaip naujo ryšio užmezgimo pradžią. Atsakymo pakete PacketNumber laukas padidinamas vienu, informuojant siuntėją apie sėkmingą pirmojo paketo gavimą. Options laukas naudojamas perduoti pranešimo dydį, leidžiant gavėjui žinoti, kiek duomenų tikėtis.

Ryšys Uždarymas Pasibaigus Laikui

Jei ryšys nutrūksta arba adresatas tampa nepasiekiamas, Patikimas UDP protokolas turi gebėti tinkamai uždaryti ryšį ir atlaisvinti išteklius. Tai pasiekiama naudojant laikmačius. Jei siuntėjas negauna patvirtinimo per nustatytą laiką, jis gali pakartotinai siųsti paketus arba galiausiai nutraukti ryšį. Panašiai, gavėjo pusėje, jei laukiamas paketas negaunamas, suveikia laikmatis, kuris gali inicijuoti pakartotinį siuntimą arba, jei problema išlieka, ryšio uždarymą.

Duomenų Perdavimo Atkūrimas

Viena iš svarbiausių Patikimo UDP funkcijų yra duomenų perdavimo atkūrimas. Kai paketas prarandamas, gavėjas gali siųsti prašymą pakartotinai jį pristatyti (RequestForPacket vėliavėlė). Siuntėjas, gavęs tokį prašymą, pakartotinai siunčia prarastą paketą. Šis mechanizmas, kartu su perdavimo lango naudojimu, leidžia efektyviai atkurti prarastus duomenis ir užtikrinti, kad visas pranešimas būtų pristatytas teisingai.

TCP vs UDP Comparison | Cisco CCNA 200-301

Patikima UDP API Išvada

Patikimo UDP protokolo įgyvendinimas suteikia galimybę naudoti UDP greitį ir paprastumą kartu su garantuotu duomenų pristatymu, būtinu daugeliui aplikacijų. Jis leidžia efektyviai perduoti didelius duomenų kiekius, palaikyti ryšius ir atkurti prarastus duomenis, tuo pačiu išlaikant galimybę veikti kaip „grynas“ UDP.

Šis protokolas yra vertingas įrankis kuriant patikimas ir efektyvias tinklo aplikacijas, ypač tose srityse, kur tradicinis TCP gali būti per lėtas, o grynas UDP - per nepatikimas.

Naudingos Nuorodos ir Straipsniai

  • RFC 768: User Datagram Protocol
  • RFC 793: Transmission Control Protocol
  • RFC 908: Reliable Data Protocol (RDTP)
  • RFC 1151: Simple Network Management Protocol (SNMP) - Nors RFC 1151 yra apie SNMP, paminėtas kaip nuoroda į ankstesnius patikimų protokolų standartus.
  • QUIC (Quick UDP Internet Connections) - Google sukurtas protokolas, naudojantis UDP su patobulintais patikimumo ir saugumo mechanizmais.

tags: #udp #protokola #duomenu #keitimuisi