Տվյալների հուսալի փոխանցման հիմունքները

Տվյալների հուսալի փոխանցման հիմունքները

Դրանց համար, ովքեր փորձում են հասկանալ ցանցերն ու արձանագրությունները, նվիրում է:

Կարճ

Այս հոդվածում քննարկվում են վստահելի տեղեկատվության փոխանցման հիմունքները, օրինակներ են բերվում Go, այդ թվում UDP և TCP: Մաթեմատիկացիա մեկ, երկուս, երեք և "Համակարգչային ցանցեր: Ներդաշնակ մոտեցում" գիրքը, քանի որ բոլորը միայն Թանենբաումի և Օլիֆերների մասին են խոսում:

Առանձնահատված արձանագրություն

Բացահայտում է տրամաբանական կապը տարբեր հոստինգների միջև, որոնք գործում են տարբեր հոսքերի վրա: Տրամաբանական կապը կիրառման տեսանկյունից երևում է որպես ալիք, որը անմիջապես կապում է հոսքերը:

Տվյալների հուսալի փոխանցման հիմունքները

Առանձնահատված արձանագրությունները պահվում են վերջնական համակարգերով, բայց ոչ ցանցային ուղղորդիչներով (բացի — DPI). Ուղարկողի կողմում առանձին մատչելի արձանագրությունը փոխակերպում է կիրառման մակարդակի տվյալները, որոնք ստանում է փոխանցվող կիրառման մակարդակի գործընթացից, առանձին տակառների, որոնք կոչվում են հատվածներ:

Տվյալների հուսալի փոխանցման հիմունքները

Այս իրականացվում է կիրառման մակարդակի հաղորդագրությունների (հնարավորության դեպքում) կտորներին բաժանելով և յուրաքանչյուրին հավելելով առանձին արձանագրության մակարդակի գլխիկ:

Տվյալների հուսալի փոխանցման հիմունքները

Առաջ գնում առանձին հատվածը դեպի ուղարկողի ցանցային մակարդակ, որտեղ հատվածը համակցվում է ցանցային մակարդակի տակառի մեջ (դյուրգամ) և ուղարկվում է: Ընդունող կողմում ցանցային մակարդակը դուրս է բերում առանձին հատվածը դյուրգամից և փոխանցում այն վերև դեպի առանձին մակարդակ: Այնուհետև, առանձին մակարդակը մշակել է ստացված հատվածը այդ կերպ, որ դրա տվյալներն հասանելի լինեն ընդունող կիրառմանը:

Տվյալների հուսալի փոխանցման հիմունքները

Վստահելի տեղեկատվության փոխանցման սկզբունքներ

Վստահելի տեղեկատվության փոխանցում նվազագույնս վստահելի ալիքի միջոցով

Ժամանակակից դեպք: Առաքելու կողմը պարզապես ընդունում է բարձր մակարդակի տվյալները, ստեղծում է դրանք պարունակող տակառ և ուղարկում է դրանք ալիքին:

Սերվեր

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 + վստահելի ալիք
    }
}

Հաճախորդը

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

Հավաստի տվյալների փոխանցում ալիքով, որտեղ հնարավոր են սխալներ

Հաջորդ փուլը ենթադրում է, որ բոլոր փոխանցված փաթեթները ստացվել են այն կարգով, որով դրանք ուղարկվել են, բայց բիթերը կարող են վնասվել, քանի որ ալիքը երբեմն փոխանցում է տվյալները խեղաթյուրումներներով:

Տվյալների հուսալի փոխանցման հիմունքները

Այս դեպքում կիրառվում են մեխանիզմներ:

  • սխալի հայտնաբերում;
  • դյուրին կապ;
  • ղեկավար վերաբաշխում:

Հավաստի տվյալների փոխանցման պրոկոտոլները, որոնք ունեն նմանատիպ մեխանիզմներ բազմակի վերաբաշխման համար, կոչվում են ավտոմատ պարբերաբար վերաբաշխման հարցման պրոկոտոլներ (Automatic Repeat reQuest, ARQ):
Ավելորդ է կանխատեսել սխալների հնարավորությունները և ընդունման դրոշմաններում, երբ ընդունող կողմը չի ստանում որևէ տեղեկություն փոխանցման վերջին փաթեթի արդյունքների վերաբերյալ:
Այս խնդրի լուծումը, որը նաև օգտագործվում է TCP-ում, բաղկացած է տվյալների փաթեթներին նոր դաշտ ավելացնելուց, որը պարունակում է փաթեթի հերթական համարը:

Տվյալների հուսալի փոխանցման հիմունքները

Հավաստի տվյալների փոխանցում անհավատալի ալիքով, որը թույլ է տալիս խեղաթյուրումներ և փաթեթների կորուստներ

Խեղաթյուրումների հետ միասին, ցավոք, ցանցում հանդիպում են փաթեթների կորուստներ:
Այս խնդրի լուծման համար պահանջվում են մեխանիզմներ:

  • փաթեթների կորուստը որոշելու;
  • կորած փաթեթների վերաբաշխում ընդունող կողմին:

Ավելին, կորած փաթեթից բացի, հարկավոր է նախազգուշացնել պատվականության կորելությունը, կամ եթե ոչինչ չի կորել, այն հասանելի է նշանակալի ուշացումով: Մեծամասամբ կատարվում է նույնը: Փաթեթի կրկնակի տեղափոխման համար ժամանակը վերահսկելու մեխանիզմում օգտագործվում է հաշվարկի ժամացույց, որը թույլ է տալիս սահմանել սպասման ժամկետի ավարտը: Այստեղ ` net TCPKeepAlive պարամետրը ենթադրվում է 15 վայրկյան ըստ նախադրյալի:

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

Ուղարկող կողմը պետք է սկսել ժամացույցը յուրաքանչյուր անգամ փաթեթի փոխանցման ժամանակ (ինչպես առաջին, այնպես էլ կրկնակի) `տ amserի խափանումները և կանգնեցնել այն:

Եկեք ծանոթանանք տվյալների կայուն փոխանցման պրոկոտոլների հիմնական հասկացություններին:

  • ռազմավարական ստուգման գումարներ;
  • համարային փաթեթների;
  • ժամաչափերով;
  • դրական և բացասական ընդունման ծանուցումներով.

Սակայն սա դեռ ամենը չէ!

Տվյալների վստահության փոխանցման արձանագրություն ոլորակավորման հետ

Ավելի վաղ քննարկված տարբերակում, վստահության փոխանցման արձանագրությունը շատ անարդյունավետ է։ Այն սկսում է «դանդաղեցնել» փոխանցումը, որն ապահովում է կապի ալիքը, երբ RTT-ն մեծանում է։ Նրա արդյունավետությունը բարձրացնելու համար, կապի ալիքի անցանելիության լավ օգտագործման համար կիրառվում է ոլորակում:

Տվյալների հուսալի փոխանցման հիմունքները

Ոլորակավորման կիրառումը հանգեցնում է:

  • համարային մարկաների ընդլայնման, քանի որ բոլոր ուղարկվող փաթեթները (անկախ կրկնակի փոխանցումներից) պետք է միանշանակ ճանաչելի լինեն;
  • փոխանցման և ընդունման կողմերում բուֆերների մեծացման անհրաժեշտությանը.

Համարային մարկաների շրջանակն ու բուֆերի չափերի պահանջները կապված են արձանագրության գործողությունների հետ՝ ձգձգման, կորուստի և փաթեթի դանդաղեցման պատասխաններից: Ոլորակավորման պարագայում գոյություն ունեն երկու սխալների ուղղման մեթոդներ:

  • N փաթեթներով ետ վերադարձ;
  • ընտրողական կրկնություն.

N փաթեթներով ետ վերադարձը՝ սահնակային պատուհանի արձանագրություն

Տվյալների հուսալի փոխանցման հիմունքները

Ուղեցույցը պետք է պահպանեն երեք տեսակի իրադարձություններ:

  • բարձր մակարդակի արձանագրության կողմից կանչ: Երբ «հրահանգ» է տրվում տվյալների փոխանցման գործառույթ, փոխանցող կողմը նախ ճշտում է պատուհանի լրացման աստիճանը (այսինքն՝ N ուղարկված հաղորդագրությունների առկայությունը, որոնք սպասում են ընդունման ծանուցման): Եթե պատուհանը բավականաչափ լեցուն չէ, նոր փաթեթ է ձեւավորվում և փոխանցվում, իսկ փոփոխականների արժեքները թարմացվում են: Այլ դեպքում, փոխանցող կողմը վերադարձնում է տվյալները բարձր մակարդակին, և սա դառնում է բացարձակ նշան, որ պատուհանը լցված է: սովորաբար բարձր մակարդակը կրկնակի փորձ է կատարում տվյալների փոխանցման համար որոշ ժամանակ անց: Կիրառման մեջ, հաղորդուղին, ամենայն հավանականությամբ, կամ տվյալները բուֆերային կլինի (միանգամյա փոխանցման փոխարեն), կամ կունենա սինխրոնացման մեխանիզմ (օրինակ՝ սեմաֆոր կամ դրոշ), որը թույլ կտա բարձր մակարդակին տվյալներ փոխանցելու գործառույթ զանգահարել միայն թափանցիկ պատուհանի դեպքում:
  • հաստատվելու ստացում: Նրանց կոչով N դիրքի համար տրամադրվում է ընդհանուր ընդունման ծանուցում, որտեղ նշվում է, որ N-ից առաջ եկող բոլոր թվանշանային փաթեթները հաջողությամբ ընդունվել են.
  • սպասման ժամանակահատվածի ավարտ: Փաթեթների և ընդունման ծանուցումների կորուստների և դանդաղեցումների փաստերը պարզելու համար արձանագրությունը օգտագործում է ժամանակաչափ: Եթե սպասման ժամանակը ավարտվում է, փոխանցող կողմը կրկին ուղարկում է բոլոր ուղարկված հաստատված փաթեթները.

Ընտրողական կրկնություն

Երբ պատուհանի չափերը և անցումային ունակությունները սնուցման ուշացումը մեծ են, խողովակում կարող է գտնվել շատ պակտեր: Այդ դեպքում մի պակտի սխալը կարող է հանգեցնել բազմաթիվ պակտերի կրկնական փոխանցման, որոնցից շատերը անհրաժեշտ չէին:

Առաջարկ

Լ mejores թեորական պրակտիկայի լավագույն քայլերը հավաքված են պրակտիկական իրականացման մեջ TCP. Եթե ինչ-որ մեկը գիտի, թե ինչպես կարելի է ավելի լավ անել՝ Բարի գալուստ.

Սերվեր

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)
        }
        // հաղորդագրությունը թուղթում
        fmt.Print("Առաքված հաղորդագրությունը:", string(msg))
        // ստացողի վերափոխում
        newMsg := strings.ToUpper(msg)
        // տվյալների փոխանցում
        conn.Write([]byte(newMsg + "n"))
    }
}

Հաճախորդը

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, 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("Պատասխան Server-ից: " + msg)
    }
}

Ամփոփում

Գործիքներ, որոնք ապահովում են տվյալների վստահելի փոխանցումը և դրանց օգտագործումը

Գործիք
Դիմում, մեկնաբանություն

Հաշվի ստուգման
Առաջին իսկության վերզգացողություն՝ առնված պակտի բիթային սխալները հայտնաբերելու համար

Ժամաչափ
Նிրգումներ սպասելու և դրա ավարտի նշում: Վերջինն իրականացնում է այն, որ բարձր ճնշմամբ պակտը կամ դրա հավաստագիրը կորչել է փոխանցման ընթացքում: Եթե պակտը հասցնում է ուշացումով, բայց չի կորում (ամբողջ ընթացքում շեղված ժամաչափի), կամ տեղի է ունենում հավաստագրի կորուստ, կրկին փոխանցումը բերում է պակտի կրկնության ընդունող կողմում

Համարային թիվ
Օգտագործվում է տվյալների պակտերի հերթական համարումը ուղարկողից բացվողին: Հեռանալների զարգացման հանգստի համար, ձեռք բերողների կորուստը թույլ է տալիս զոհի հաստատման բացակայությունը: Միևնույն համարային հրամանակները ցույց են տալիս, որ պակտերը միմյանց կրկնում են

ՆConfirmed
Ստացվում է ստացող կողմի կողմից և ցուցադրում է պաշտպանող կողմին, որ համապատասխան պակտի կամ պակտերի խումբը հաջողությամբ է ընդունված: Առաջին հաստատումը պարունակում է հաջողությամբ ընդունված պակտերի համարայիններ: Գործող մեթոդով ավելանում են անհատական և խմբային հաստատումները

Հակառակ հաստատում
Տեղեկացնում է ուղարկողին, որ ստացողն ընդունել է փաթեթը սխալ: Վիճարկվող հաստատման մեջ սովորաբար ներառվում է այն փաթեթի հերթական թիվը, որը չի ընդունվել ճիշտ:

Պուպ, պտտում
Քաղաքականություն, որը սահմանափակում է այն հերթական համարների ծ范围ը, որոնք կարող են օգտագործվել փաթեթների փոխանցման համար: Խմբային փոխանցումն ու ձեռք սեղմումը զգալիորեն մեծացնում են համակցվածության վարկանիշը՝ համեմատած հաստատման սպասման ռեժիմի հետ: Ինչպես կտեսնենք, կենտրոնացված չափը կարող է հաշվարկվել ընդունող կողմի ընդունող ու բուֆերային հնարավորությունների և ցանցի ծանրաբեռնվածության աստիճանի հիման վրա:

Գործնական օրինակներ Go-ի օգտագործմամբ ցանցի համար:

Մեույն ռեպոզիտորիայում.

Ընտանիք: habr.com

Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով 🔥 Գնել հուսալի հյուրընկալում DDoS պաշտպանությամբ, VPS VDS սերվերներով | ProHoster