Základy spolehlivého přenosu dat

Základy spolehlivého přenosu dat

Těm, kteří hledá Oddaný porozumění sítím a protokolům.

Stručně

Článek pojednává o základech spolehlivého přenosu dat, implementuje příklady na Govčetně UDP a TCP. Na základě čas, два, tři a knihy "Počítačové sítě. Přístup shora dolů", jinak všichni diskutují jen Tannenbaum a Oliferov.

Protokol transportní vrstvy

Poskytuje logické spojení mezi aplikačními procesy běžícími na různých hostitelích. Z pohledu aplikace vypadá logické spojení jako kanál, který přímo spojuje procesy.

Základy spolehlivého přenosu dat

Protokoly transportní vrstvy jsou podporovány koncovými systémy, ale ne síťovými směrovači (kromě - DPI). Na straně odesílatele převádí transportní vrstva data aplikační vrstvy, která přijímá z procesu odesílající aplikace, na pakety transportní vrstvy nazývané segmenty.

Základy spolehlivého přenosu dat

To se provádí rozdělením (v případě potřeby) zpráv aplikační vrstvy na fragmenty a přidáním záhlaví transportní vrstvy ke každé z nich.

Základy spolehlivého přenosu dat

Transportní vrstva pak předá segment síťové vrstvě odesílatele, kde je segment zapouzdřen do paketu síťové vrstvy (datagram) a odeslán. Na přijímacím konci síťová vrstva extrahuje segment transportní vrstvy z datagramu a předá jej transportní vrstvě. Dále transportní vrstva zpracuje přijatý segment tak, aby jeho data byla k dispozici přijímající aplikaci.

Základy spolehlivého přenosu dat

Principy spolehlivého přenosu dat

Spolehlivý přenos dat přes zcela bezpečný kanál

Nejjednodušší případ. Odesílající strana jednoduše přijme data z horní vrstvy, vytvoří paket, který je obsahuje, a odešle je do kanálu.

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

Spolehlivý přenos dat přes kanál s možnými chybami

Dalším krokem je předpokládat, že všechny přenášené pakety jsou přijímány v pořadí, v jakém byly odeslány, ale bity v nich mohou být poškozeny kvůli skutečnosti, že kanál někdy přenáší data se zkreslením.

Základy spolehlivého přenosu dat

V tomto případě se používají následující mechanismy:

  • detekce chyb;
  • zpětná vazba;
  • retransmisi.

Spolehlivé protokoly přenosu dat, které mají podobné mechanismy pro vícenásobné opakování přenosu, se nazývají protokoly ARQ (Automatic Repeat ReQuest).
Navíc stojí za zvážení možnost chyb v účtenkách, kdy přijímající strana neobdrží žádné informace o výsledcích přenosu posledního paketu.
Řešením tohoto problému, používaného také v TCP, je přidat do datového paketu nové pole obsahující pořadové číslo paketu.

Základy spolehlivého přenosu dat

Spolehlivý přenos dat přes nespolehlivý kanál podléhající zkreslení a ztrátě paketů

Spolu se zkreslením bohužel dochází v síti ke ztrátě paketů.
A k vyřešení tohoto problému jsou zapotřebí mechanismy:

  • určení skutečnosti ztráty paketů;
  • opětovné doručení ztracených paketů přijímající straně.

Kromě ztráty balíku je navíc nutné počítat s možností ztráty účtenky nebo, pokud se nic neztratí, jejího doručení s výrazným zpožděním. Ve všech případech se dělá to samé: paket je znovu odeslán. K řízení času tento mechanismus využívá odpočítávací časovač, který umožňuje určit konec čekacího intervalu. Tedy v balíčku síť TCPKeepAlive je standardně nastaveno na 15 sekund:

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

Odesílající strana potřebuje spustit časovač pokaždé, když je paket přenesen (jak poprvé, tak podruhé), zvládnout přerušení od časovače a zastavit jej.

Seznámili jsme se tedy s klíčovými koncepty spolehlivých protokolů přenosu dat:

  • kontrolní součty;
  • pořadová čísla balíčků;
  • časovače;
  • kladné a záporné příjmy.

Ale to není všechno!

Spolehlivý protokol přenosu dat s pipeliningem

Ve variantě, kterou jsme již zvažovali, je spolehlivý doručovací protokol velmi neefektivní. Začíná „zpomalovat“ přenos poskytovaný komunikačním kanálem, jak se zvyšuje RTT. Pro zvýšení jeho efektivity a lepší využití kapacity komunikačního kanálu se používá pipelining.

Základy spolehlivého přenosu dat

Použití potrubí vede k:

  • zvýšení rozsahu sekvenčních čísel, protože všechny odeslané pakety (kromě opakovaných přenosů) musí být jednoznačně identifikovány;
  • potřeba zvýšit vyrovnávací paměti na vysílací a přijímací straně.

Rozsah pořadových čísel a požadavky na velikost vyrovnávací paměti závisí na akcích, které protokol provádí v reakci na poškození, ztrátu a zpoždění paketů. V případě potrubí existují dva způsoby opravy chyb:

  • vrátit N paketů zpět;
  • selektivní opakování.

Návrat N paketů - protokol posuvného okna

Základy spolehlivého přenosu dat

Odesílatel musí podporovat tři typy událostí:

  • volání protokolem vyšší úrovně. Když se funkce odesílání dat nazývá „shora“, odesílající strana nejprve zkontroluje míru zaplnění okna (tj. přítomnost N odeslaných zpráv čekajících na příjem potvrzení). Pokud je okno prázdné, vygeneruje se a odešle se nový paket a aktualizují se hodnoty proměnných. Jinak odesílající strana vrací data do horní vrstvy, což je implicitní indikace, že okno je plné. Obvykle se horní vrstva po nějaké době pokusí přenést data znovu. Ve skutečné aplikaci by odesílatel pravděpodobně data buď uložil do vyrovnávací paměti (místo okamžitého odeslání), nebo by měl synchronizační mechanismus (jako je semafor nebo příznak), který by horní vrstvě umožnil volat funkci send pouze v případě, že je okno prázdné. .
  • přijímání potvrzení. V protokolu je pro paket s pořadovým číslem N vydáno obecné potvrzení indikující, že všechny pakety s pořadovými čísly předcházejícími N byly úspěšně přijaty.
  • čekací interval vypršel. Pro zjištění skutečností ztrát a zpoždění paketů a příjmu používá protokol časovač. Pokud vyprší časový limit, odesílající strana znovu odešle všechny odeslané nepotvrzené pakety.

Selektivní opakování

Když je velikost okna a produkt zpoždění šíření propustnosti velký, může být v potrubí velký počet paketů. V takovém případě může chyba jediného paketu způsobit opětovné odeslání velkého počtu paketů, z nichž většina nebyla vyžadována.

příklad

Top teoretický praxe jsou shromažďovány v praktické implementaci TCP. A pokud někdo ví, jak nejlépe - vítejte.

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

Mechanismy pro zajištění spolehlivého přenosu a používání dat

Механизм
Přihláška, komentář

Kontrolní součet
Používá se k detekci bitových chyb v přenášeném paketu

Časový spínač
Odpočítává časový limit a ukazuje, kdy vypršel. To druhé znamená, že s vysokou mírou pravděpodobnosti dojde ke ztrátě paketu nebo jeho příjmu během přenosu. Pokud je paket doručen se zpožděním, ale neztratí se (předčasné vypršení časového limitu), nebo se ztratí potvrzení, opakovaný přenos vede k duplicitnímu paketu na straně příjemce

Sériové číslo
Používá se pro sekvenční číslování datových paketů přenášených od odesílatele k příjemci. Mezery v pořadových číslech přijatých paketů umožňují přijímači detekovat ztrátu paketů. Stejná sekvenční čísla paketů znamenají, že pakety jsou navzájem duplikáty

Potvrzení
Generováno přijímajícím koncem a indikující odesílajícímu konci, že odpovídající paket nebo skupina paketů byla úspěšně přijata. Potvrzení obvykle obsahuje pořadová čísla úspěšně přijatých paketů. V závislosti na protokolu se rozlišují individuální a skupinová potvrzení

Negativní potvrzení
Používá příjemce k informování odesílatele, že paket byl přijat nesprávně. Negativní potvrzení obvykle obsahuje pořadové číslo paketu, který nebyl správně přijat

Okno, dopravník
Omezte rozsah sekvenčních čísel, která lze použít k přenosu paketů. Multicast a handshake mohou výrazně zvýšit propustnost protokolu ve srovnání s čekáním na potvrzení. Jak uvidíme, velikost okna lze vypočítat na základě možností příjmu a ukládání do vyrovnávací paměti přijímajícího konce a také úrovně zatížení sítě

Další příklady použití Go for networking

В úložišť.

Zdroj: www.habr.com

Přidat komentář