Základy spoľahlivého prenosu údajov

Základy spoľahlivého prenosu údajov

Tým, ktorí hľadá Venované porozumeniu sietí a protokolov.

krátko

Článok rozoberá základy spoľahlivého prenosu dát, implementuje príklady na Govrátane UDP a TCP. Založené na čas, два, tri a knihy "Počítačové siete. Prístup zhora nadol", inak všetci diskutujú len o Tannenbaumovi a Oliferovi.

Protokol transportnej vrstvy

Poskytuje logické spojenie medzi aplikačnými procesmi bežiacimi na rôznych hostiteľoch. Z pohľadu aplikácie vyzerá logické spojenie ako kanál, ktorý priamo spája procesy.

Základy spoľahlivého prenosu údajov

Protokoly transportnej vrstvy sú podporované koncovými systémami, ale nie sieťovými smerovačmi (okrem - DPI). Na strane odosielateľa transportná vrstva konvertuje dáta aplikačnej vrstvy, ktoré prijíma z procesu odosielajúcej aplikácie, na pakety transportnej vrstvy nazývané segmenty.

Základy spoľahlivého prenosu údajov

To sa vykonáva rozdelením (ak je to potrebné) správ aplikačnej vrstvy na fragmenty a pridaním hlavičky transportnej vrstvy ku každej z nich.

Základy spoľahlivého prenosu údajov

Transportná vrstva potom odovzdá segment do sieťovej vrstvy odosielateľa, kde je segment zapuzdrený do paketu sieťovej vrstvy (datagram) a odoslaný. Na prijímacom konci sieťová vrstva extrahuje segment transportnej vrstvy z datagramu a odovzdá ho transportnej vrstve. Potom transportná vrstva spracuje prijatý segment tak, aby jeho údaje boli dostupné pre prijímajúcu aplikáciu.

Základy spoľahlivého prenosu údajov

Zásady spoľahlivého prenosu dát

Spoľahlivý prenos dát cez úplne bezpečný kanál

Najjednoduchší prípad. Odosielajúca strana jednoducho prijme dáta z hornej vrstvy, vytvorí paket, ktorý ich obsahuje, a odošle ich do kanála.

Server

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 + надежный канал
    }
}

zákazník

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

Spoľahlivý prenos dát cez kanál s možnými chybami

Ďalším krokom je predpokladať, že všetky prenášané pakety sú prijaté v poradí, v akom boli odoslané, ale bity v nich môžu byť poškodené v dôsledku skutočnosti, že kanál niekedy prenáša dáta so skreslením.

Základy spoľahlivého prenosu údajov

V tomto prípade sa používajú nasledujúce mechanizmy:

  • detekcia chýb;
  • spätná väzba;
  • retransmisiu.

Spoľahlivé protokoly prenosu údajov, ktoré majú podobné mechanizmy na viacnásobné opakovanie prenosu, sa nazývajú protokoly ARQ (Automatic Repeat ReQuest).
Okrem toho stojí za zváženie možnosť chýb v potvrdeniach, keď prijímajúca strana nedostane žiadne informácie o výsledkoch prenosu posledného paketu.
Riešením tohto problému, ktorý sa používa aj v TCP, je pridanie nového poľa do dátového paketu obsahujúceho poradové číslo paketu.

Základy spoľahlivého prenosu údajov

Spoľahlivý prenos dát cez nespoľahlivý kanál podliehajúci skresleniu a strate paketov

Spolu so skreslením bohužiaľ dochádza v sieti k strate paketov.
A na vyriešenie tohto problému sú potrebné mechanizmy:

  • určenie skutočnosti straty paketov;
  • opätovné doručenie stratených paketov prijímajúcej strane.

Okrem straty balíka je navyše potrebné počítať s možnosťou straty účtenky, alebo ak sa nič nestratí, jej doručenia s výrazným oneskorením. Vo všetkých prípadoch sa robí to isté: paket sa odošle znova. Na ovládanie času tento mechanizmus využíva odpočítavací časovač, ktorý umožňuje určiť koniec čakacieho intervalu. Takže v balíku sieť TCPKeepAlive je predvolene nastavené na 15 sekúnd:

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

Odosielajúca strana potrebuje spustiť časovač pri každom prenose paketu (prvý aj druhýkrát), zvládnuť prerušenia od časovača a zastaviť ho.

Oboznámili sme sa teda s kľúčovými konceptmi spoľahlivých protokolov prenosu údajov:

  • kontrolné súčty;
  • poradové čísla balíkov;
  • časovače;
  • pozitívne a negatívne príjmy.

Ale to nie je všetko!

Spoľahlivý protokol prenosu dát s pipeliningom

Vo variante, ktorý sme už zvažovali, je spoľahlivý protokol doručenia veľmi neefektívny. Začína „spomaľovať“ prenos poskytovaný komunikačným kanálom so zvyšujúcim sa RTT. Na zvýšenie jeho efektívnosti a lepšie využitie kapacity komunikačného kanála sa používa pipelining.

Základy spoľahlivého prenosu údajov

Použitie potrubia vedie k:

  • zvýšenie rozsahu sekvenčných čísel, pretože všetky odoslané pakety (okrem opakovaných prenosov) musia byť jednoznačne identifikované;
  • potreba zvýšiť nárazníky na vysielacej a prijímacej strane.

Rozsah sekvenčných čísel a požiadavky na veľkosť vyrovnávacej pamäte závisia od akcií, ktoré protokol vykoná v reakcii na poškodenie, stratu a oneskorenie paketu. V prípade potrubia existujú dva spôsoby opravy chýb:

  • vrátiť N paketov späť;
  • selektívne opakovanie.

Návrat N paketov - protokol posuvného okna

Základy spoľahlivého prenosu údajov

Odosielateľ musí podporovať tri typy udalostí:

  • volať protokolom vyššej úrovne. Keď sa funkcia odosielania dát volá „zhora“, odosielajúca strana najskôr skontroluje mieru zaplnenia okna (čiže prítomnosť N odoslaných správ čakajúcich na príjem potvrdení). Ak je okno prázdne, vygeneruje sa a odošle nový paket a aktualizujú sa hodnoty premenných. V opačnom prípade odosielajúca strana vráti údaje do hornej vrstvy, čo je implicitná indikácia, že okno je plné. Horná vrstva sa zvyčajne pokúsi po určitom čase znova preniesť údaje. V skutočnej aplikácii by odosielateľ pravdepodobne údaje buď uložil do vyrovnávacej pamäte (namiesto ich okamžitého odoslania), alebo by mal synchronizačný mechanizmus (napríklad semafor alebo príznak), ktorý by umožnil vyššej vrstve volať funkciu odoslania iba vtedy, keď je okno prázdne. .
  • prijímanie potvrdenia. V protokole sa pre paket so sekvenčným číslom N vydá všeobecné potvrdenie, ktoré indikuje, že všetky pakety so sekvenčnými číslami predchádzajúcimi N boli úspešne prijaté.
  • čakací interval vypršal. Na zistenie skutočností o stratách a oneskoreniach paketov a príjmov používa protokol časovač. Ak uplynie časový limit, odosielajúca strana znova odošle všetky odoslané nepotvrdené pakety.

Selektívne opakovanie

Keď sú veľkosť okna a súčin oneskorenia šírenia priepustnosti veľké, v potrubí môže byť veľký počet paketov. V takom prípade môže chyba jedného paketu spôsobiť opätovné odoslanie veľkého počtu paketov, z ktorých väčšina nebola potrebná.

Príklad

Top teoretická postupy sa zhromažďujú pri praktickej implementácii TCP. A ak niekto vie ako najlepšie... vitajte.

Server

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

zákazník

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

Výkon

Mechanizmy na zabezpečenie spoľahlivého prenosu a používania údajov

mechanizmus
Aplikácia, komentár

Kontrolná suma
Používa sa na detekciu bitových chýb v prenášanom pakete

časomerač
Odpočítava časový limit a indikuje, kedy vypršal. To znamená, že s vysokou pravdepodobnosťou sa paket alebo jeho príjem počas prenosu stratia. Ak je paket doručený s oneskorením, ale nestratí sa (predčasné uplynutie časového limitu), alebo sa stratí potvrdenie, opakovaný prenos vedie k duplicitnému paketu na strane príjemcu

Sériové číslo
Používa sa na postupné číslovanie dátových paketov prenášaných od odosielateľa k príjemcovi. Medzery v sekvenčných číslach prijatých paketov umožňujú prijímaču zistiť stratu paketov. Rovnaké poradové čísla paketov znamenajú, že pakety sú navzájom duplikáty

potvrdenie
Generované prijímajúcim koncom a indikujúce odosielajúcemu koncu, že zodpovedajúci paket alebo skupina paketov bola úspešne prijatá. Typicky potvrdenie obsahuje poradové čísla úspešne prijatých paketov. V závislosti od protokolu sa rozlišujú individuálne a skupinové potvrdenia

Negatívne potvrdenie
Používa sa príjemcom na informovanie odosielateľa, že paket bol prijatý nesprávne. Negatívne potvrdenie zvyčajne obsahuje poradové číslo paketu, ktorý nebol správne prijatý

Okno, dopravník
Obmedzte rozsah sekvenčných čísel, ktoré možno použiť na prenos paketov. Multicast a handshake môžu výrazne zvýšiť priepustnosť protokolu v porovnaní s čakaním na potvrdenia. Ako uvidíme, veľkosť okna možno vypočítať na základe možností príjmu a vyrovnávacej pamäte prijímajúceho konca, ako aj úrovne zaťaženia siete

Ďalšie príklady používania Go for networking

В úložiská.

Zdroj: hab.com

Pridať komentár