Grundvallaratriði áreiðanlegs gagnaflutnings

Grundvallaratriði áreiðanlegs gagnaflutnings

Til þeirra sem leitar Tileinkað því að skilja netkerfi og samskiptareglur.

Í stuttu máli

Greinin fjallar um grunnatriði áreiðanlegrar gagnaflutnings, útfærir dæmi um Go, þar á meðal UDP og TCP. Byggt á tími, два, þrír og bækurnar "Computer Networks. Top-Down Approach", annars eru allir að ræða aðeins Tannenbaum og Oliferov.

Samskiptareglur um flutningslag

Veitir rökrétta tengingu milli umsóknarferla sem keyra á mismunandi vélum. Frá sjónarhóli umsóknar lítur rökrétt tenging út eins og rás sem tengir ferla beint.

Grundvallaratriði áreiðanlegs gagnaflutnings

Samskiptareglur um flutningslag eru studd af endakerfum, en ekki af netbeinum (nema - DPI). Á sendandahliðinni breytir flutningslagið gögnum forritalagsins sem það fær frá sendandi umsóknarferlinu í flutningslagapakka sem kallast hluti.

Grundvallaratriði áreiðanlegs gagnaflutnings

Þetta er gert með því að skipta (ef nauðsyn krefur) skilaboðum forritslagsins í brot og bæta flutningslagshaus við hvert þeirra.

Grundvallaratriði áreiðanlegs gagnaflutnings

Flutningslagið ber síðan hlutann yfir í netlag sendanda, þar sem hluti er hjúpaður inn í netlagspakka (datagram) og sendur. Við móttökuendann dregur netlagið út flutningslagshlutann úr gagnagramminu og sendir það upp í flutningslagið. Næst vinnur flutningslagið úr mótteknum hluta þannig að gögn þess verða aðgengileg móttökuforritinu.

Grundvallaratriði áreiðanlegs gagnaflutnings

Meginreglur um áreiðanlega gagnaflutning

Áreiðanleg gagnasending á fullkomlega öruggri rás

Einfaldasta málið. Sendandi hliðin tekur einfaldlega við gögnunum frá efra laginu, býr til pakka sem inniheldur þau og sendir þau á rásina.

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

Viðskiptavinur

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

Áreiðanleg gagnasending yfir rás með hugsanlegum villum

Næsta skref er að gera ráð fyrir að allir sendir pakkar séu mótteknir í þeirri röð sem þeir voru sendir, en bitarnir í þeim geta verið skemmdir vegna þess að rásin sendir stundum gögn með röskun.

Grundvallaratriði áreiðanlegs gagnaflutnings

Í þessu tilviki eru eftirfarandi aðferðir notaðar:

  • villugreining;
  • endurgjöf;
  • endursending.

Áreiðanlegar samskiptareglur fyrir gagnaflutning sem hafa svipaðar aðferðir til að endurtaka sendingu margsinnis eru kallaðar Automatic Repeat reQuest (ARQ) samskiptareglur.
Að auki er þess virði að íhuga möguleikann á villum í kvittunum, þegar viðtakandi mun ekki fá neinar upplýsingar um niðurstöður flutnings síðasta pakkans.
Lausnin á þessu vandamáli, sem einnig er notað í TCP, er að bæta nýjum reit við gagnapakkann sem inniheldur raðnúmer pakkans.

Grundvallaratriði áreiðanlegs gagnaflutnings

Áreiðanleg gagnasending um óáreiðanlega rás sem er háð pakkaröskun og tapi

Samhliða röskun er því miður pakkatap á netinu.
Og til að leysa þetta vandamál þarf aðgerðir:

  • ákvarða staðreynd pakkataps;
  • endursending tapaðra pakka til móttökuaðila.

Auk þess, til viðbótar við tap á pakkanum, er nauðsynlegt að gera ráð fyrir möguleikanum á því að kvittunin glatist eða, ef ekkert tapast, afhendingu hennar með verulegum töfum. Í öllum tilvikum er það sama gert: pakkinn er endursendur. Til að stjórna tíma notar þessi vélbúnaður niðurtalningartíma, sem gerir þér kleift að ákvarða lok biðtímans. Svo í pakkanum nettó TCPKeepAlive er sjálfgefið stillt á 15 sekúndur:

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

Sendandi hlið þarf að ræsa tímamæli í hvert sinn sem pakki er sendur (bæði í fyrsta og annað skiptið), sjá um truflanir frá tímamælinum og stöðva hann.

Þannig að við höfum kynnst lykilhugtökum áreiðanlegra gagnaflutningssamskiptareglna:

  • tékkupphæðir;
  • raðnúmer pakka;
  • tímamælir;
  • jákvæðar og neikvæðar viðtökur.

En það er ekki allt!

Áreiðanleg gagnaflutningsaðferð með leiðslum

Í afbrigðinu sem við höfum þegar íhugað er áreiðanleg afhendingaraðferð mjög óhagkvæm. Það byrjar að „hægja á“ sendingunni frá samskiptarásinni þegar RTT eykst. Til að auka skilvirkni þess og nýta betur afkastagetu samskiptarásarinnar er notuð leiðsla.

Grundvallaratriði áreiðanlegs gagnaflutnings

Notkun leiðsla leiðir til:

  • auka svið raðnúmera, þar sem allir sendir pakkar (nema endursendingar) verða að vera auðkenndir á einkvæman hátt;
  • nauðsyn þess að auka biðminni á sendi- og móttökuhliðum.

Kröfur um röð númerasviðs og biðminnisstærðar eru háðar aðgerðunum sem samskiptareglur grípa til til að bregðast við spillingu, tapi og töfum pakka. Þegar um leiðslur er að ræða eru tvær aðferðir til að leiðrétta villur:

  • skila N pökkum til baka;
  • sértæk endurtekning.

Farið til baka N pakkar - siðareglur með renna glugga

Grundvallaratriði áreiðanlegs gagnaflutnings

Sendandi verður að styðja við þrenns konar atburði:

  • hringja með samskiptareglum á hærra stigi. Þegar gagnasendingaraðgerðin er kölluð „að ofan“, athugar sendandi hliðin fyrst hversu fyllt gluggann er (þ.e. tilvist N sendra skilaboða sem bíða móttöku kvittana). Ef glugginn er tómur er nýr pakki búinn til og sendur og breytugildin eru uppfærð. Annars skilar sendihliðin gögnum í efra lagið og þetta er óbein vísbending um að glugginn sé fullur. Venjulega mun efra lagið reyna að senda gögnin aftur eftir nokkurn tíma. Í raunverulegu forriti myndi sendandinn líklega annaðhvort biðja gögnin í biðminni (í stað þess að senda þau strax) eða hafa samstillingarkerfi (eins og semafór eða fána) sem myndi leyfa efra lagið að kalla á sendingaraðgerðina aðeins þegar glugginn er tómur .
  • að fá staðfestingu. Í samskiptareglunni, fyrir pakka með raðnúmer N, er gefin út almenn viðurkenning sem gefur til kynna að allir pakkar með raðnúmer á undan N hafi verið mótteknir.
  • biðtíminn er liðinn. Til að ákvarða staðreyndir um tap og tafir á pökkum og kvittunum, notar siðareglur tímamæli. Ef fresturinn rennur út sendir sendandi aftur alla sendu óviðurkennda pakka.

Sértæk endurtekning

Þegar gluggastærðin og afköst-útbreiðslu seinkun vara eru stór, getur mikill fjöldi pakka verið í pípunum. Í slíku tilviki getur ein pakkavilla valdið því að mikill fjöldi pakka sé endursendur, sem flestir voru ekki nauðsynlegir.

Dæmi

Top fræðilegt starfsvenjum er safnað í verklegri framkvæmd TCP. Og ef einhver veit hvernig best - velkomnir.

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

Viðskiptavinur

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

Aðferðir til að tryggja áreiðanlega gagnaflutning og notkun

Vélbúnaður
Umsókn, athugasemd

Athugaðu summa
Notað til að greina bitavillur í sendum pakka

Tímamælir
Telur niður tímabilið og gefur til kynna hvenær það er útrunnið. Hið síðarnefnda þýðir að með miklum líkum glatast pakkinn eða kvittun hans við sendingu. Ef pakki er afhentur með töf, en glatast ekki (ótímabært rennur út tímamörk), eða kvittun glatast, leiðir endursending til afrits pakka á móttökuhliðinni

Raðnúmer
Notað til að raðnúmera gagnapakka sem eru sendir frá sendanda til viðtakanda. Eyður í raðnúmerum móttekinna pakka gera viðtakandanum kleift að greina pakkatap. Sömu raðnúmer pakka þýðir að pakkarnir eru afrit hver af öðrum

Staðfesting
Myndað af móttökuendanum og gefur til kynna fyrir sendandanum að samsvarandi pakki eða pakkahópur hafi verið móttekinn. Venjulega inniheldur staðfestingin raðnúmer pakka sem hafa tekist vel. Það fer eftir bókun, einstaklings- og hópfestingar eru aðgreindar

Neikvæð staðfesting
Notað af viðtakanda til að tilkynna sendanda að pakkinn hafi verið móttekinn rangt. Neikvæð staðfesting inniheldur venjulega raðnúmer pakkans sem var ekki rétt móttekið

Gluggi, færiband
Takmarkaðu svið raðnúmera sem hægt er að nota til að senda pakka. Fjölvarp og handtak geta aukið samskiptaafköst verulega samanborið við að bíða eftir staðfestingum. Eins og við munum sjá er hægt að reikna gluggastærðina út frá móttöku- og biðminnisgetu móttökuendans, sem og netálagsstigi

Fleiri dæmi um notkun Go fyrir netkerfi

В geymslum.

Heimild: www.habr.com

Bæta við athugasemd