Grondbeginsels van betroubare data-oordrag

Grondbeginsels van betroubare data-oordrag

Aan diegene wat soek Toegewyd aan die begrip van netwerke en protokolle.

kortliks

Die artikel bespreek die basiese beginsels van betroubare data-oordrag, implementeer voorbeelde oor Go, insluitend UDP en TCP. Gebaseer op tyd, два, 3 en die boeke "Computer Networks. Top-Down Approach", anders bespreek almal net Tannenbaum en Oliferov.

Vervoerlaagprotokol

Verskaf 'n logiese verband tussen toepassingsprosesse wat op verskillende gashere loop. Vanuit 'n toepassingsperspektief lyk 'n logiese verband soos 'n kanaal wat prosesse direk verbind.

Grondbeginsels van betroubare data-oordrag

Vervoerlaagprotokolle word ondersteun deur eindstelsels, maar nie deur netwerkrouters nie (behalwe - DPI). Aan die senderkant omskep die vervoerlaag die toepassingslaagdata wat dit van die stuurtoepassingsproses ontvang om in vervoerlaagpakkies wat segmente genoem word.

Grondbeginsels van betroubare data-oordrag

Dit word gedoen deur (indien nodig) die toepassingslaagboodskappe in fragmente te verdeel en 'n vervoerlaagopskrif by elkeen van hulle te voeg.

Grondbeginsels van betroubare data-oordrag

Die vervoerlaag gee dan die segment deur na die sender se netwerklaag, waar die segment in 'n netwerklaagpakkie (datagram) ingekapsuleer en gestuur word. Aan die ontvangkant onttrek die netwerklaag die vervoerlaagsegment uit die datagram en gee dit op na die vervoerlaag. Vervolgens verwerk die vervoerlaag die ontvangde segment sodat sy data beskikbaar word vir die ontvangende toepassing.

Grondbeginsels van betroubare data-oordrag

Beginsels van betroubare data-oordrag

Betroubare data-oordrag oor 'n heeltemal veilige kanaal

Die eenvoudigste geval. Die stuurkant ontvang eenvoudig die data van die boonste laag, skep 'n pakkie wat dit bevat en stuur dit na die kanaal.

Bediener

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

kliënt

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

Betroubare data-oordrag oor 'n kanaal met moontlike foute

Die volgende stap is om te aanvaar dat alle versendte pakkies ontvang word in die volgorde waarin hulle gestuur is, maar die stukkies daarin kan korrupteer wees as gevolg van die feit dat die kanaal soms data met vervormings oordra.

Grondbeginsels van betroubare data-oordrag

In hierdie geval word die volgende meganismes gebruik:

  • foutopsporing;
  • terugvoer;
  • heruitsending.

Betroubare data-oordragprotokolle wat soortgelyke meganismes het om oordrag verskeie kere te herhaal, word Automatic Repeat ReQuest (ARQ)-protokolle genoem.
Daarbenewens is dit die moeite werd om die moontlikheid van foute in kwitansies te oorweeg, wanneer die ontvangende party geen inligting oor die resultate van die oordrag van die laaste pakkie sal ontvang nie.
Die oplossing vir hierdie probleem, wat ook in TCP gebruik word, is om 'n nuwe veld by die datapakkie te voeg wat die volgordenommer van die pakkie bevat.

Grondbeginsels van betroubare data-oordrag

Betroubare data-oordrag oor 'n onbetroubare kanaal onderhewig aan pakkievervorming en verlies

Saam met vervorming is daar ongelukkig pakkieverlies in die netwerk.
En om hierdie probleem op te los, is meganismes nodig:

  • die bepaling van die feit van pakkieverlies;
  • heraflewering van verlore pakkies aan die ontvangende party.

Benewens die verlies van die pakket, is dit nodig om voorsiening te maak vir die moontlikheid van verlies van die kwitansie of, indien niks verlore gaan nie, die aflewering daarvan met 'n aansienlike vertraging. In alle gevalle word dieselfde gedoen: die pakkie word weer versend. Om tyd te beheer, gebruik hierdie meganisme 'n afteltydhouer, wat jou toelaat om die einde van die waginterval te bepaal. So in die pakkie netto TCPKeepAlive is by verstek op 15 sekondes gestel:

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

Die stuurkant moet 'n timer begin elke keer as 'n pakkie versend word (beide die eerste en die tweede keer), onderbrekings van die tydhouer hanteer en dit stop.

So, ons het vertroud geraak met die sleutelkonsepte van betroubare data-oordragprotokolle:

  • kontrolesomme;
  • volgordenommers van pakkette;
  • timers;
  • positiewe en negatiewe kwitansies.

Maar dit is nie al nie!

Betroubare data-oordragprotokol met pypleiding

In die variant wat ons reeds oorweeg het, is die betroubare afleweringsprotokol baie ondoeltreffend. Dit begin die transmissie wat deur die kommunikasiekanaal verskaf word "vertraag" soos die RTT toeneem. Om die doeltreffendheid daarvan te verhoog en die kommunikasiekanaalkapasiteit beter te benut, word pypleiding gebruik.

Grondbeginsels van betroubare data-oordrag

Die gebruik van pypleiding lei tot:

  • verhoging van die reeks volgordenommers, aangesien alle gestuurde pakkies (behalwe vir heruitsendings) uniek geïdentifiseer moet word;
  • die behoefte om buffers aan die stuur- en ontvangkant te verhoog.

Die reeksnommerreeks en buffergroottevereistes hang af van die aksies wat die protokol neem in reaksie op pakkiekorrupsie, verlies en vertraging. In die geval van pypleiding is daar twee metodes om foute reg te stel:

  • stuur N pakkies terug;
  • selektiewe herhaling.

Gaan terug N pakkies - gly venster protokol

Grondbeginsels van betroubare data-oordrag

Die sender moet drie tipes gebeurtenisse ondersteun:

  • oproep deur 'n hoër vlak protokol. Wanneer die datastuurfunksie "van bo" genoem word, kontroleer die stuurkant eers die graad van vul van die venster (dit wil sê die teenwoordigheid van N gestuurde boodskappe wat wag op ontvangs van kwitansies). As die venster leeg is, word 'n nuwe pakkie gegenereer en versend, en die veranderlike waardes word opgedateer. Andersins stuur die stuurkant data terug na die boonste laag, en dit is 'n implisiete aanduiding dat die venster vol is. Tipies sal die boonste laag probeer om die data na 'n rukkie weer oor te dra. In 'n regte toepassing sal die sender waarskynlik óf die data buffer (in plaas daarvan om dit dadelik te stuur) óf 'n sinchronisasiemeganisme (soos 'n semafoor of vlag) hê wat die boonste laag sal toelaat om die stuurfunksie te roep slegs wanneer die venster leeg is .
  • bevestiging ontvang. In die protokol, vir 'n pakkie met volgnommer N, word 'n algemene erkenning uitgereik wat aandui dat alle pakkies met volgnommers wat N voorafgaan, suksesvol ontvang is.
  • die waginterval het verstryk. Om die feite van verliese en vertragings van pakkies en kwitansies te bepaal, gebruik die protokol 'n timer. As die uittelinterval verstryk, stuur die stuurkant alle gestuurde, nie-erkende pakkies weer.

Selektiewe herhaling

Wanneer die venstergrootte en die deurset-voortplantingsvertragingsproduk groot is, kan 'n groot aantal pakkies in die pyplyn wees. In so 'n geval kan 'n enkele pakkie fout veroorsaak dat 'n groot aantal pakkies herversend word, waarvan die meeste nie nodig was nie.

Voorbeeld

Top teoreties praktyke word in praktiese implementering ingesamel TCP. En as iemand weet hoe die beste - welkom.

Bediener

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

kliënt

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

Output

Meganismes om betroubare data-oordrag en gebruik te verseker

meganisme
Aansoek, kommentaar

Kontroleer som
Word gebruik om bisfoute in 'n versendte pakkie op te spoor

Tydopnemer
Tel die uittelinterval af en dui aan wanneer dit verstryk het. Laasgenoemde beteken dat met 'n hoë mate van waarskynlikheid die pakkie of sy kwitansie verlore gaan tydens transmissie. As 'n pakkie met 'n vertraging afgelewer word, maar nie verlore gaan nie (voortydige verstryking van die uittelinterval), of 'n kwitansie verlore gaan, lei heruitsending tot 'n duplikaatpakkie aan die ontvangkant

Reeksnommer
Word gebruik vir opeenvolgende nommering van datapakkies wat van sender na ontvanger versend is. Leemtes in die volgordenommers van ontvangde pakkies laat die ontvanger toe om pakkieverlies op te spoor. Dieselfde pakkie volgorde nommers beteken dat die pakkies is duplikate van mekaar

Bevestiging
Gegenereer deur die ontvangkant en aandui aan die stuurkant dat die ooreenstemmende pakkie of groep pakkies suksesvol ontvang is. Tipies bevat die erkenning die volgordenommers van pakkies wat suksesvol ontvang is. Afhangende van die protokol, word individuele en groepbevestigings onderskei

Negatiewe bevestiging
Word deur die ontvanger gebruik om die sender in kennis te stel dat die pakkie verkeerd ontvang is. 'n Negatiewe erkenning sluit gewoonlik die volgnommer van die pakkie in wat nie korrek ontvang is nie

Venster, vervoer
Beperk die reeks rynommers wat gebruik kan word om pakkies te versend. Multicast en handdruk kan protokol deurset aansienlik verhoog in vergelyking met wag vir erkennings. Soos ons sal sien, kan die venstergrootte bereken word op grond van die ontvangs- en buffervermoë van die ontvangkant, sowel as die netwerkladingsvlak

Meer voorbeelde van die gebruik van Go vir netwerk

В bewaarplekke.

Bron: will.com

Voeg 'n opmerking