Patikimo duomenų perdavimo pagrindai

Patikimo duomenų perdavimo pagrindai

Tiems, kurie siekia Skirta suprasti tinklus ir protokolus.

Trumpai

Straipsnyje aptariami patikimo duomenų perdavimo pagrindai, pateikiami pavyzdžiai Go, įskaitant UDP ir TCP. Remiantis laikas, два, trys ir knygos "Kompiuteriniai tinklai. Požiūris iš viršaus į apačią", šiaip visi diskutuoja tik apie Tannenbaumą ir Oliferovą.

Transporto sluoksnio protokolas

Užtikrina loginį ryšį tarp taikomųjų programų procesų, veikiančių skirtinguose pagrindiniuose kompiuteriuose. Programos požiūriu loginis ryšys atrodo kaip kanalas, tiesiogiai jungiantis procesus.

Patikimo duomenų perdavimo pagrindai

Transporto lygmens protokolai palaiko galinės sistemos, bet ne tinklo maršrutizatoriai (išskyrus DPI). Siuntėjo pusėje transporto sluoksnis konvertuoja taikomojo sluoksnio duomenis, gautus iš siuntimo programos proceso, į transportavimo lygmens paketus, vadinamus segmentais.

Patikimo duomenų perdavimo pagrindai

Tai atliekama padalinant (jei reikia) programos sluoksnio pranešimus į fragmentus ir prie kiekvieno iš jų pridedant transporto sluoksnio antraštę.

Patikimo duomenų perdavimo pagrindai

Tada transportavimo sluoksnis perduoda segmentą į siuntėjo tinklo sluoksnį, kur segmentas įterpiamas į tinklo sluoksnio paketą (duomenųgramą) ir išsiunčiamas. Priėmimo gale tinklo sluoksnis iš datagramos ištraukia transporto sluoksnio segmentą ir perduoda jį transportavimo sluoksniui. Tada transporto sluoksnis apdoroja gautą segmentą, kad jo duomenys taptų prieinami priimančiajai programai.

Patikimo duomenų perdavimo pagrindai

Patikimo duomenų perdavimo principai

Patikimas duomenų perdavimas visiškai saugiu kanalu

Paprasčiausias atvejis. Siunčianti pusė tiesiog gauna duomenis iš viršutinio sluoksnio, sukuria paketą su jais ir siunčia į kanalą.

Serveris

package main

import (
    "log"
    "net"
)

func main() {
    // IP-адрес сервера и порт
    serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
    if err != nil {
        log.Fatal(err)
    }

    // создаем сокет с портом
    serverConn, err := net.ListenUDP("udp", serverAddr)
    if err != nil {
        log.Fatal(err)
    }
    // отложенное закрытие соединения
    defer serverConn.Close()

    // создаем буфер для данных
    buf := make([]byte, 1024)

    // ждем соединение
    for {
        // читаем запрос
        n, addr, err := serverConn.ReadFromUDP(buf)
        // передаем данные в ВЕРХНИЙ уровень: в нашем случае stdout
        println(string(buf[0:n]), " form ", addr.IP.String())
        if err != nil {
            log.Fatal(err)
        }
        // ответа нет, т.к. это UDP + надежный канал
    }
}

Klientas

package main

import (
    "fmt"
    "log"
    "net"
    "time"
)

func main() {
    // IP-адрес сервера и порт
    serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
    if err != nil {
        log.Fatal(err)
    }
    // локальный IP-адрес и порт
    localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
    if err != nil {
        log.Fatal(err)
    }
    // установка соединения
    conn, err := net.DialUDP("udp", localAddr, serverAddr)
    if err != nil {
        log.Fatal(err)
    }
    // отложенное закрытие соединения
    defer conn.Close()

    for {
        // получение данных от ВЕРХНЕГО уровня
        fmt.Print("Введите строчное предложение > ")
        var msg string
        _, err := fmt.Scanf("%s", &msg)
        if err != nil {
            log.Fatal(err)
        }
        // передается поток байт, а не строка
        buf := []byte(msg)
        // запись (передача) в соединение
        _, err = conn.Write(buf)
        if err != nil {
            log.Fatal(err)
        }
        // 1 секундочку
        time.Sleep(time.Second * 1)
    }
}

Patikimas duomenų perdavimas kanalu su galimomis klaidomis

Kitas žingsnis – daryti prielaidą, kad visi perduoti paketai gaunami tokia tvarka, kokia buvo išsiųsti, tačiau juose esantys bitai gali būti sugadinti dėl to, kad kanalas kartais perduoda duomenis su iškraipymais.

Patikimo duomenų perdavimo pagrindai

Šiuo atveju naudojami šie mechanizmai:

  • klaidų aptikimas;
  • Atsiliepimas;
  • retransliacija.

Patikimi duomenų perdavimo protokolai, turintys panašius perdavimo kelis kartus kartojimo mechanizmus, vadinami automatinio kartojimo užklausos (ARQ) protokolais.
Be to, verta pagalvoti apie klaidų galimybę kvituose, kai gaunančioji šalis negaus jokios informacijos apie paskutinio paketo perdavimo rezultatus.
Šios problemos sprendimas, taip pat naudojamas TCP, yra pridėti naują lauką prie duomenų paketo, kuriame yra paketo eilės numeris.

Patikimo duomenų perdavimo pagrindai

Patikimas duomenų perdavimas nepatikimu kanalu dėl paketų iškraipymo ir praradimo

Kartu su iškraipymais, deja, tinkle prarandami ir paketai.
Ir norint išspręsti šią problemą, reikalingi mechanizmai:

  • paketų praradimo fakto nustatymas;
  • pamestų paketų pakartotinis pristatymas gaunančiajai šaliai.

Be to, be pakuotės praradimo, būtina numatyti galimybę prarasti kvitą arba, jei nieko neprarandama, pristatyti jį gerokai vėluojant. Visais atvejais daroma ta pati: paketas persiunčiamas. Laikui valdyti šis mechanizmas naudoja atgalinės atskaitos laikmatį, leidžiantį nustatyti laukimo intervalo pabaigą. Taigi pakuotėje neto Pagal numatytuosius nustatymus TCPKeepAlive nustatytas 15 sekundžių:

// defaultTCPKeepAlive is a default constant value for TCPKeepAlive times
// See golang.org/issue/31510
const (
    defaultTCPKeepAlive = 15 * time.Second
)

Siunčianti pusė turi paleisti laikmatį kiekvieną kartą, kai siunčiamas paketas (ir pirmą, ir antrą kartą), tvarkyti laikmačio trikdžius ir jį sustabdyti.

Taigi, mes susipažinome su pagrindinėmis patikimų duomenų perdavimo protokolų sąvokomis:

  • kontrolinės sumos;
  • pakuočių eilės numeriai;
  • laikmačiai;
  • teigiami ir neigiami kvitai.

Bet tai dar ne viskas!

Patikimas duomenų perdavimo protokolas su vamzdynais

Mūsų jau svarstytame variante patikimas pristatymo protokolas yra labai neefektyvus. Didėjant RTT, jis pradeda „lėtinti“ ryšio kanalo teikiamą perdavimą. Siekiant padidinti jo efektyvumą ir geriau išnaudoti ryšio kanalo pajėgumus, naudojamas vamzdynas.

Patikimo duomenų perdavimo pagrindai

Vamzdynų naudojimas lemia:

  • eilės numerių diapazono didinimas, nes visi siunčiami paketai (išskyrus pakartotinius siuntimus) turi būti unikaliai identifikuoti;
  • poreikis padidinti buferius siuntimo ir priėmimo pusėse.

Eilės numerių diapazonas ir buferio dydžio reikalavimai priklauso nuo veiksmų, kuriuos protokolas atlieka reaguodamas į paketų sugadinimą, praradimą ir vėlavimą. Vamzdynų klojimo atveju yra du klaidų ištaisymo būdai:

  • grąžinti N paketų atgal;
  • selektyvus kartojimas.

Grįžtant atgal N paketų – stumdomo lango protokolas

Patikimo duomenų perdavimo pagrindai

Siuntėjas turi palaikyti trijų tipų įvykius:

  • skambinti aukštesnio lygio protokolu. Kai duomenų siuntimo funkcija vadinama „iš viršaus“, siunčiančioji pusė pirmiausia patikrina lango užpildymo laipsnį (tai yra, ar yra N išsiųstų pranešimų, laukiančių gavimo kvitų). Jei langas tuščias, generuojamas ir perduodamas naujas paketas, atnaujinamos kintamųjų reikšmės. Kitu atveju siunčianti pusė grąžina duomenis į viršutinį sluoksnį, ir tai yra netiesioginis požymis, kad langas pilnas. Paprastai viršutinis sluoksnis po kurio laiko vėl bandys perduoti duomenis. Tikroje programoje siuntėjas greičiausiai arba buferuotų duomenis (o ne iš karto išsiųstų) arba turės sinchronizacijos mechanizmą (pvz., semaforą ar vėliavėlę), kuris leistų viršutiniam sluoksniui iškviesti siuntimo funkciją tik tada, kai langas tuščias. .
  • gauti patvirtinimą. Protokole paketui su eilės numeriu N išduodamas bendras patvirtinimas, nurodantis, kad visi paketai, kurių eilės numeriai yra prieš N, buvo sėkmingai gauti.
  • laukimo intervalas baigėsi. Paketų ir kvitų praradimo ir vėlavimo faktams nustatyti protokole naudojamas laikmatis. Jei laikas pasibaigia, siunčiančioji pusė iš naujo siunčia visus išsiųstus nepatvirtintus paketus.

Atrankinis kartojimas

Kai lango dydis ir pralaidumo plitimo delsos produktas yra dideli, gali būti ruošiamas didelis paketų skaičius. Tokiu atveju dėl vieno paketo klaidos gali būti pakartotinai perduota daug paketų, kurių dauguma nebuvo reikalingi.

Pavyzdys

Viršus teorinis praktika renkama praktiškai įgyvendinant TCP. Ir jei kas nors žino, kaip geriausia - laukiamas.

Serveris

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "strings"
)

func main() {
    // создаем сокет с портом 
    ln, err := net.Listen("tcp", ":8081")
    if err != nil {
        log.Fatalln(err)
    }
    // ожидание вызова
    conn, _ := ln.Accept()

    for {
        // считывание данных
        msg, err := bufio.NewReader(conn).ReadString('n')
        if err != nil {
            log.Fatalln(err)
        }
        // вывод сообщения в stdout
        fmt.Print("Message Received:", string(msg))
        // перевод строки в верхний регистр
        newMsg := strings.ToUpper(msg)
        // отправка данных
        conn.Write([]byte(newMsg + "n"))
    }
}

Klientas

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "os"
)

func main() {
    // установка соединения
    conn, err := net.Dial("tcp", "127.0.0.1:8081")
    if err != nil {
        log.Fatalln(err)
    }

    for {
        // считывание данных с stdin
        reader := bufio.NewReader(os.Stdin)
        fmt.Print("Text to send: ")
        // построчно
        text, err := reader.ReadString('n')
        if err != nil {
            log.Fatalln(err)
        }
        // отправка
        fmt.Fprintf(conn, text+"n")
        // прием
        msg, err := bufio.NewReader(conn).ReadString('n')
        if err != nil {
            log.Fatalln(err)
        }
        // вывод полученного ответа
        fmt.Print("Msg from Server: " + msg)
    }
}

Produkcija

Mechanizmai, užtikrinantys patikimą duomenų perdavimą ir naudojimą

Mechanizmas
Paraiška, komentaras

Patikrinkite sumą
Naudojamas perduodamo paketo bitų klaidoms aptikti

Laikmatis
Skaičiuoja skirtojo laiko intervalą ir nurodo, kada jis pasibaigė. Pastarasis reiškia, kad siuntimo metu labai tikėtina, kad paketas arba jo gavimas prarandamas. Jei paketas pristatomas pavėluotai, bet neprarandamas (priešlaikinis laiko intervalo pasibaigimas) arba pametamas kvitas, pakartotinis siuntimas veda prie dublikato paketo gavimo pusėje.

Serijos numeris
Naudojamas nuosekliai numeruoti duomenų paketus, perduodamus iš siuntėjo gavėjui. Gautų paketų eilės numerių spragos leidžia imtuvui aptikti paketų praradimą. Tie patys paketų eilės numeriai reiškia, kad paketai yra vienas kito dublikatai

Patvirtinimas
Sugeneruoja priėmimo galas ir nurodo siuntimo galui, kad atitinkamas paketas arba paketų grupė buvo sėkmingai gauti. Paprastai patvirtinime yra sėkmingai gautų paketų eilės numeriai. Priklausomai nuo protokolo, skiriami individualūs ir grupiniai patvirtinimai

Neigiamas patvirtinimas
Naudoja gavėjas informuodamas siuntėją, kad paketas gautas neteisingai. Neigiamas patvirtinimas paprastai apima neteisingai gauto paketo eilės numerį

Langas, konvejeris
Apribokite eilės numerių diapazoną, kuris gali būti naudojamas paketams perduoti. Daugialypė transliacija ir rankos paspaudimas gali žymiai padidinti protokolo pralaidumą, palyginti su laukimu, kol laukiama patvirtinimų. Kaip matysime, lango dydis gali būti apskaičiuojamas pagal priėmimo ir buferio galimybes, taip pat tinklo apkrovos lygį.

Daugiau „Go“ naudojimo tinkle pavyzdžių

В saugyklos.

Šaltinis: www.habr.com

Добавить комментарий