Bazat e transferimit të besueshëm të të dhënave

Bazat e transferimit të besueshëm të të dhënave

Për ata që kërkon Përkushtuar për të kuptuar rrjetet dhe protokollet.

pak

Artikulli diskuton bazat e transmetimit të besueshëm të të dhënave, zbaton shembuj Go, duke përfshirë UDP dhe TCP. Bazuar në kohë, два, tre dhe librat "Rrjetet kompjuterike. Qasje nga lart-poshtë", përndryshe të gjithë po diskutojnë vetëm Tannenbaum dhe Oliferov.

Protokolli i shtresës së transportit

Ofron një lidhje logjike midis proceseve të aplikimit që ekzekutohen në hoste të ndryshëm. Nga këndvështrimi i aplikacionit, një lidhje logjike duket si një kanal që lidh drejtpërdrejt proceset.

Bazat e transferimit të besueshëm të të dhënave

Protokollet e shtresave të transportit mbështeten nga sistemet fundore, por jo nga ruterat e rrjetit (përveç - DPI). Nga ana e dërguesit, shtresa e transportit i konverton të dhënat e shtresës së aplikacionit që merr nga procesi i dërgimit të aplikacionit në paketa të shtresës së transportit të quajtur segmente.

Bazat e transferimit të besueshëm të të dhënave

Kjo bëhet duke ndarë (nëse është e nevojshme) mesazhet e shtresës së aplikacionit në fragmente dhe duke shtuar një kokë të shtresës së transportit në secilën prej tyre.

Bazat e transferimit të besueshëm të të dhënave

Më pas, shtresa e transportit e kalon segmentin në shtresën e rrjetit të dërguesit, ku segmenti kapsulohet në një paketë të shtresës së rrjetit (datagram) dhe dërgohet. Në fundin marrës, shtresa e rrjetit nxjerr segmentin e shtresës së transportit nga datagrami dhe e kalon atë në shtresën e transportit. Më pas, shtresa e transportit përpunon segmentin e marrë në mënyrë që të dhënat e tij të bëhen të disponueshme për aplikacionin marrës.

Bazat e transferimit të besueshëm të të dhënave

Parimet e transmetimit të besueshëm të të dhënave

Transmetim i besueshëm i të dhënave përmes një kanali plotësisht të sigurt

Rasti më i thjeshtë. Ana dërguese thjesht merr të dhënat nga shtresa e sipërme, krijon një paketë që e përmban atë dhe ia dërgon kanalit.

Serveri

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

klient

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

Transmetim i besueshëm i të dhënave përmes një kanali me gabime të mundshme

Hapi tjetër është të supozohet se të gjitha paketat e transmetuara janë marrë në rendin në të cilin janë dërguar, por bitet në to mund të jenë të dëmtuara për shkak të faktit se kanali ndonjëherë transmeton të dhëna me shtrembërime.

Bazat e transferimit të besueshëm të të dhënave

Në këtë rast, përdoren mekanizmat e mëposhtëm:

  • zbulimi i gabimeve;
  • reagime;
  • ritransmetim.

Protokollet e besueshme të transferimit të të dhënave që kanë mekanizma të ngjashëm për përsëritjen e transmetimit disa herë quhen protokolle të kërkesës së përsëritur automatike (ARQ).
Për më tepër, vlen të merret parasysh mundësia e gabimeve në fatura, kur pala marrëse nuk do të marrë asnjë informacion në lidhje me rezultatet e transferimit të paketës së fundit.
Zgjidhja për këtë problem, e përdorur gjithashtu në TCP, është shtimi i një fushe të re në paketën e të dhënave që përmban numrin e sekuencës së paketës.

Bazat e transferimit të besueshëm të të dhënave

Transmetim i besueshëm i të dhënave përmes një kanali jo të besueshëm që i nënshtrohet shtrembërimit dhe humbjes së paketës

Së bashku me shtrembërimin, për fat të keq, ka humbje të paketave në rrjet.
Dhe për të zgjidhur këtë problem, kërkohen mekanizma:

  • përcaktimi i faktit të humbjes së paketës;
  • ridorëzimi i paketave të humbura te pala marrëse.

Përveç kësaj, përveç humbjes së paketës, është e nevojshme të parashikohet mundësia e humbjes së faturës ose, nëse asgjë nuk humbet, dërgimi i saj me një vonesë të konsiderueshme. Në të gjitha rastet, bëhet e njëjta gjë: paketa ritransmetohet. Për të kontrolluar kohën, ky mekanizëm përdor një kohëmatës numërimi mbrapsht, i cili ju lejon të përcaktoni fundin e intervalit të pritjes. Pra në paketë neto TCPKeepAlive është caktuar si parazgjedhje në 15 sekonda:

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

Pala dërguese duhet të fillojë një kohëmatës sa herë që transmetohet një paketë (si herën e parë ashtu edhe herën e dytë), të trajtojë ndërprerjet nga kohëmatësi dhe ta ndalojë atë.

Pra, ne jemi njohur me konceptet kryesore të protokolleve të besueshme të transferimit të të dhënave:

  • shumat e kontrollit;
  • numrat e sekuencës së paketave;
  • kohëmatës;
  • faturat pozitive dhe negative.

Por kjo nuk është e gjitha!

Protokoll i besueshëm i transferimit të të dhënave me tubacion

Në variantin që kemi shqyrtuar tashmë, protokolli i besueshëm i dorëzimit është shumë joefikas. Ai fillon të "ngadalësojë" transmetimin e ofruar nga kanali i komunikimit ndërsa RTT rritet. Për të rritur efikasitetin e tij dhe për të shfrytëzuar më mirë kapacitetin e kanalit të komunikimit, përdoret tubacioni.

Bazat e transferimit të besueshëm të të dhënave

Përdorimi i tubacioneve çon në:

  • duke rritur gamën e numrave të sekuencës, pasi të gjitha paketat e dërguara (përveç ritransmetimeve) duhet të identifikohen në mënyrë unike;
  • nevoja për të rritur buferët në anët transmetuese dhe marrëse.

Diapazoni i numrit të sekuencës dhe kërkesat e madhësisë së tamponit varen nga veprimet që kryen protokolli në përgjigje të korrupsionit, humbjes dhe vonesës së paketave. Në rastin e tubacionit, ekzistojnë dy metoda për korrigjimin e gabimeve:

  • ktheni mbrapsht N pako;
  • përsëritje selektive.

Kthimi i N paketave - protokoll i dritares rrëshqitëse

Bazat e transferimit të besueshëm të të dhënave

Dërguesi duhet të mbështesë tre lloje ngjarjesh:

  • telefononi me një protokoll të nivelit më të lartë. Kur funksioni i dërgimit të të dhënave quhet "nga lart", pala dërguese së pari kontrollon shkallën e mbushjes së dritares (d.m.th. praninë e N mesazheve të dërguara që presin marrjen e faturave). Nëse dritarja është bosh, gjenerohet dhe transmetohet një paketë e re, dhe vlerat e variablave përditësohen. Përndryshe, pala dërguese i kthen të dhënat në shtresën e sipërme dhe ky është një tregues i nënkuptuar se dritarja është plot. Në mënyrë tipike, shtresa e sipërme do të përpiqet të transmetojë të dhënat përsëri pas njëfarë kohe. Në një aplikacion real, dërguesi ka të ngjarë të ruajë të dhënat (në vend që t'i dërgojë ato menjëherë) ose të ketë një mekanizëm sinkronizimi (siç është një semafor ose flamur) që do të lejonte shtresën e sipërme të thërrasë funksionin e dërgimit vetëm kur dritarja është bosh. .
  • marrjen e konfirmimit. Në protokoll, për një paketë me numrin e sekuencës N, lëshohet një konfirmim i përgjithshëm që tregon se të gjitha paketat me numra sekuencash që paraprijnë N-në janë marrë me sukses.
  • intervali i pritjes ka skaduar. Për të përcaktuar faktet e humbjeve dhe vonesave të paketave dhe pranimeve, protokolli përdor një kohëmatës. Nëse skadon intervali i skadimit, pala dërguese i ridërgon të gjitha paketat e dërguara të papranuara.

Përsëritje selektive

Kur madhësia e dritares dhe produkti i vonesës së përhapjes së xhiros janë të mëdha, një numër i madh paketash mund të jenë në linjë. Në një rast të tillë, një gabim i vetëm pakete mund të shkaktojë që një numër i madh paketash të ritransmetohen, shumica e të cilave nuk kërkoheshin.

Shembull

Më të mirët teorike praktikat mblidhen në zbatimin praktik TCP. Dhe nëse dikush e di se sa më mirë - i mirëpritur.

Serveri

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

klient

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

Prodhim

Mekanizmat për të siguruar transferim dhe përdorim të besueshëm të të dhënave

mekanizëm
Aplikim, koment

Kontrollo shumën
Përdoret për të zbuluar gabimet e bitit në një paketë të transmetuar

kohëmatës
Numëron mbrapsht intervalin e skadimit dhe tregon se kur ka skaduar. Kjo e fundit do të thotë që me një shkallë të lartë probabiliteti paketa ose marrja e saj humbet gjatë transmetimit. Nëse një paketë dorëzohet me vonesë, por nuk humbet (skadimi i parakohshëm i intervalit të skadimit), ose humbet një faturë, ritransmetimi çon në një paketë dublikatë në anën marrëse

Numër serik
Përdoret për numërimin sekuencial të paketave të të dhënave të transmetuara nga dërguesi te marrësi. Boshllëqet në numrat e sekuencës së paketave të marra lejojnë marrësin të zbulojë humbjen e paketave. Të njëjtat numra të sekuencës së paketave nënkuptojnë se paketat janë dublikatë të njëra-tjetrës

Vërtetim
Gjeneruar nga fundi marrës dhe duke treguar në fundin dërgues që paketa përkatëse ose grupi i paketave është marrë me sukses. Në mënyrë tipike, konfirmimi përmban numrat e sekuencës së paketave të pranuara me sukses. Në varësi të protokollit dallohen konfirmimet individuale dhe grupore

Konfirmim negativ
Përdoret nga marrësi për të informuar dërguesin se paketa është marrë gabimisht. Një konfirmim negativ zakonisht përfshin numrin e sekuencës së paketës që nuk është marrë saktë

Dritare, transportues
Kufizoni gamën e numrave të sekuencës që mund të përdoren për të transmetuar paketa. Multicast dhe shtrëngimi i duarve mund të rrisin ndjeshëm shpejtësinë e protokollit në krahasim me pritjen për mirënjohje. Siç do të shohim, madhësia e dritares mund të llogaritet bazuar në aftësitë e marrjes dhe buferimit të skajit marrës, si dhe në nivelin e ngarkesës së rrjetit

Më shumë shembuj të përdorimit të Go për rrjetëzim

В depove.

Burimi: www.habr.com

Shto një koment