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

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

Atij që po synojnë të kuptojnë rrjetet dhe protokollet, i dedikohet.

Në përmbledhje

Në këtë artikull shqyrtohen të gjithë bazat e transmetimit të sigurt të të dhënave, duke ilustruar shembuj në Go, përfshirë UDP dhe TCP. Në frymëzuar nga një, dy, tre dhe libri "Rrjetet kompjuterike. Qasja nga poshtë", pasi të gjithë flasin vetëm për Tanenbaum dhe Olifer.

Protokolli i nivelit transportues

garanton një lidhje logjike midis proceseve aplikative që po ekzekutohen në hoste të ndryshme. Lidhja logjike nga perspektiva e aplikacioneve duket si një kanal që lidh drejtpërdrejt proceset.

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

Protokollet e nivelit transportues mbështeten nga sistemet e fundit, por jo nga ruterët rrjetit (përveç - DPI). Në anën e dërguesit, niveli transportues kthen të dhënat e nivelit aplikativ që merr nga procesi aplikativ dërgues në paketa të nivelit transportues, të quajtura segmente.

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

Kjo realizohet duke copëtuar (në rast nevoje) mesazhet e nivelit aplikativ në fragmente dhe duke shtuar një kokëz të nivelit transportues në secilin prej tyre.

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

Pastaj, niveli transportues dërgon segmentin në nivelin rrjetit të dërguesit, ku segmenti inkapsulohet në një paketë të nivelit rrjetit (datagram) dhe dërgohet. Në anën e marrësit, niveli rrjetit nxjerr segmentin e nivelit transportues nga datagrami dhe e transmeton lart në nivelin transportues. Pastaj niveli transportues 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 transmetimit të besueshëm të të dhënave

Parimet e transmetimit të sigurt të të dhënave

Transmetimi i sigurt i të dhënave përmes një kanali krejtësisht të besueshëm

Rasti më i thjeshtë. Anëtari dërgues thjesht merr të dhënat nga niveli i lartë, krijon paketën që i përmban ato dhe e dërgon në kanal.

Server

paketa kryesore

import (
    "log"
    "net"
)

funksioni kryesor() {
    \/\/ Adresa IP e serverit dhe porta
    serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
    nëse err != nil {
        log.Fatal(err)
    }

    \/\/ krijo një socket me portin
    serverConn, err := net.ListenUDP("udp", serverAddr)
    nëse err != nil {
        log.Fatal(err)
    }
    \/\/ mbyllja e vonuar e lidhjes
    defer serverConn.Close()

    \/\/ krijo një tampon për të dhënat
    buf := make([]byte, 1024)

    \/\/ presim lidhjen
    për {
        \/\/ lexojmë kërkesën
        n, addr, err := serverConn.ReadFromUDP(buf)
        \/\/ dĂ«rgojmĂ« tĂ« dhĂ«nat nĂ« nivelin E LARTË: nĂ« rastin tonĂ« stdout
        println(string(buf[0:n]), " nga ", addr.IP.String())
        nëse err != nil {
            log.Fatal(err)
        }
        \/\/ nuk ka përgjigje, pasi ky është UDP + një kanal të besueshëm
    }
}

KÎ»ÎŻÎżÏ…ent

paketa kryesore

import (
    "fmt"
    "log"
    "net"
    "time"
)

funksioni kryesor() {
    \/\/ Adresa IP e serverit dhe porta
    serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
    nëse err != nil {
        log.Fatal(err)
    }
    \/\/ adresa lokale IP dhe porta
    localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
    nëse err != nil {
        log.Fatal(err)
    }
    \/\/ vendos lidhjen
    conn, err := net.DialUDP("udp", localAddr, serverAddr)
    nëse err != nil {
        log.Fatal(err)
    }
    \/\/ mbyllja e vonuar e lidhjes
    defer conn.Close()

    për {
        \/\/ marrja e tĂ« dhĂ«nave nga niveli I LARTË
        fmt.Print("Shkruani një frazë > ")
        var msg string
        _, err := fmt.Scanf("%s", &msg)
        nëse err != nil {
            log.Fatal(err)
        }
        \/\/ dërgohet një rrjedhë byte, jo një varg
        buf := []byte(msg)
        \/\/ shkrimi (dërgimi) në lidhje
        _, err = conn.Write(buf)
        nëse err != nil {
            log.Fatal(err)
        }
        \/\/ 1 sekondë
        time.Sleep(time.Second * 1)
    }
}

Transferi i besueshëm i të dhënave përmes një kanali me mundësi gabimesh

Hapi tjetër është të supozojmë se të gjitha paketat e dërguara janë marrë në rendin në të cilin janë dërguar, por bitet në to mund të jenë të dëmtuara, për shkak se kanali ndonjëherë dërgon të dhëna me deformime.

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

Në këtë rast, përdoren mekanizmat:

  • zbulimi i gabimeve;
  • feedback;
  • rikthimi i dĂ«rgimit.

Protokollet e besueshëm të transferimit të të dhënave që kanë mekanizma të tillë për përsëritjen e dërgimit, quhen protokolle me kërkesë automatik të përsëritjes (Automatic Repeat reQuest, ARQ).
Për më tepër, është e nevojshme të parashikohet mundësia e gabimeve edhe në konfirmimet, kur pala që pranon nuk merr asnjë informacion mbi rezultatet e transferimit të paketës së fundit.
Zgjidhja e kësaj çështjeje, e përdorur gjithashtu në TCP, përbëhet nga shtimi në paketë të një fushe të re të dhënash që përmban numrin rresht të paketës.

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

Transferimi i sigurt i të dhënave përmes një kanali të pasigurt, që pranon deformime dhe humbjen e paketimeve.

Fatkeqësisht, gjatë deformimeve, rrjeti ka gjithashtu humbje paketi.
Dhe për të zgjidhur këtë problem nevojiten mekanizma:

  • pĂ«r tĂ« pĂ«rcaktuar humbjen e paketimeve;
  • pĂ«r ri-dĂ«rgimin e paketimeve tĂ« humbura nĂ« anĂ«n e marrĂ«sit.

Për më tepër, përveç humbjes së paketës, duhet të parashikohet humbja e konfirmimit ose, nëse nuk ka asgjë të humbur, dërgimi i tij me një vonesë të konsiderueshme. Në të gjitha rastet kryhet e njëjta veprim: ri-dërgimi i paketës. Për të kontrolluar kohën në këtë mekanizëm përdoret një numërator i prishur, i cili lejon përcaktimin e përfundimit të intervalit të pritjes. Kështu, në paketë, net parametri TCPKeepAlive është vendosur në 15 sekonda si parazgjedhje:

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

Anës transmetuese duhet të aktivizojë numëratorin çdo herë kur dërgon një paketë (si në të parën ashtu edhe në ri-dërgimin), të shqyrtojë ndërprerjet nga numëratori dhe ta ndalë atë.

Pra, ne u njohëm me konceptet kryesore të protokolleve të transmetimit të sigurt të të dhënave:

  • kontrollin e shumave;
  • numrat rendorĂ« tĂ« paketimeve;
  • numĂ«ratorĂ«t;
  • konfirmimet pozitive dhe negative.

Por kjo nuk është e gjitha!

Protokolli i sigurimit të transmetimit të të dhënave me konvejering

Në atë variant që kemi shqyrtuar, protokolli i dorëzimit të sigurt është shumë i paefikas. Ai fillon "të ngadalësojë" transmetimin, duke e siguruar kanalin e komunikimit, me rritjen e RTT. Për të rritur efikasitetin e tij, përdoret konvejeringu për një shfrytëzim më të mirë të kapacitetit të kanalit të komunikimit.

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

Përdorimi i konvejeringut çon në:

  • rritjen e gamĂ«s sĂ« numrave rendorĂ«, pasi tĂ« gjithĂ« paketat e dĂ«rguara (pĂ«rveç ri-dĂ«rgesave) duhet tĂ« jenĂ« tĂ« identifikueshme qartĂ«;
  • nevojĂ«n pĂ«r rritjen e tamponĂ«ve nĂ« anĂ«n transmetuese dhe atĂ« marrĂ«se.

Gama e numrave rendorë dhe kërkesat për madhësitë e tamponëve varen nga veprimet që ndërmerr protokolli si përgjigje ndaj deformimeve, humbjeve dhe vonesave të paketimeve. Në rastin e konvejeringut ka dy metoda për korrigjimin e gabimeve:

  • kthimi mbrapa pĂ«r N paketa;
  • ribashkĂ«rkoi selektive.

Kthimi mbrapa për N paketa - protokolli i dritares së gliding

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

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

  • Đ·Đłjedhja e protokolit mĂ« tĂ« lartĂ«. Kur funksioni pĂ«r dĂ«rgimin e tĂ« dhĂ«nave thirret "nga lart", pala qĂ« dĂ«rgon sĂ« pari kontrollon shkallĂ«n e pĂ«rmbushjes sĂ« dritares (domethĂ«nĂ« prania e N mesazheve tĂ« dĂ«rguara qĂ« presin pranimin e konfirmacioneve). NĂ«se dritarja rezulton e zbrazĂ«t, formohet njĂ« paketĂ« e re dhe dĂ«rgohet, dhe vlerat e variablave pĂ«rditĂ«sohen. NĂ« tĂ« kundĂ«rt, pala qĂ« dĂ«rgon i kthen tĂ« dhĂ«nat nivelit tĂ« lartĂ«, dhe kjo Ă«shtĂ« njĂ« tregues i heshtur qĂ« dritarja Ă«shtĂ« e mbushur. Zakonisht niveli mĂ« i lartĂ« pĂ«rpiqet pĂ«rsĂ«ri tĂ« dĂ«rgojĂ« tĂ« dhĂ«nat pas njĂ« kohe. NĂ« njĂ« aplikacion real, dĂ«rguesi me shumĂ« mundĂ«si do tĂ« kishte ose bufferizuar tĂ« dhĂ«nat (nĂ« vend tĂ« dĂ«rgimit tĂ« menjĂ«hershĂ«m), ose do tĂ« kishte njĂ« mekanizĂ«m sinkronizimi (p.sh., semafor ose flamur) qĂ« do t'i lejonte nivelit mĂ« tĂ« lartĂ« tĂ« thĂ«rrasĂ« funksionin e dĂ«rgimit tĂ« tĂ« dhĂ«nave vetĂ«m kur dritarja tĂ« ishte e zbrazĂ«t.
  • marrja e konfirmimit. NĂ« protokollin pĂ«r paketĂ«n me numrin e rendit N lĂ«shohet njĂ« konfirmim i pĂ«rgjithshĂ«m qĂ« tregon se tĂ« gjitha paketat me numrat e rendit qĂ« e parashikojnĂ« N janĂ« pranuar me sukses.
  • skadimi i intervalit tĂ« pritjes. PĂ«r tĂ« pĂ«rcaktuar faktet e humbjeve dhe vonesave tĂ« paketimeve dhe konfirmacioneve protokolli pĂ«rdor njĂ« timer. NĂ«se skadon intervali i pritjes, pala qĂ« dĂ«rgon dĂ«rgon pĂ«rsĂ«ri tĂ« gjitha paketat e dĂ«rguara qĂ« nuk janĂ« konfirmuar.

Ribërja selektive

Kur madhësia e dritares dhe produkti i kapacitetit të kalimit me vonesën e shpërndarjes janë të mëdha, në tub është e mundur të ndodhen shumë paketa. Në një rast të tillë, gabimi i një pakete të veçantë mund të shkaktojë përsëritjen e dërgimit të një numri të madh paketash, shumica e të cilave nuk ishin të nevojshme.

Shembulli

MĂ« tĂ« mirat teorike praktikat janĂ« mbledhur nĂ« zbatimin praktik TCP. Dhe nĂ«se dikush di ndonjĂ« gjĂ« mĂ« tĂ« mirĂ« — mirĂ«sevini.

Server

package main

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "strings"
)

func main() {
    // krijojmë një soket me port 
    ln, err := net.Listen("tcp", ":8081")
    if err != nil {
        log.Fatalln(err)
    }
    // pritja e thirrjes
    conn, _ := ln.Accept()

    for {
        // leximi i të dhënave
        msg, err := bufio.NewReader(conn).ReadString('n')
        if err != nil {
            log.Fatalln(err)
        }
        // dalja e mesazhit në stdout
        fmt.Print("Mesazhi i Marrë:", string(msg))
        // përkthimi i vargut në shkronja të mëdha
        newMsg := strings.ToUpper(msg)
        // dërgimi i të dhënave
        conn.Write([]byte(newMsg + "n"))
    }
}

KÎ»ÎŻÎżÏ…ent

paket kryesor

import (
    "bufio"
    "fmt"
    "log"
    "net"
    "os"
)

func main() {
    \/\/ vendosja e lidhjes
    conn, err := net.Dial("tcp", "127.0.0.1:8081")
    if err != nil {
        log.Fatalln(err)
    }

    for {
        \/\/ leximi i të dhënave nga stdin
        reader := bufio.NewReader(os.Stdin)
        fmt.Print("Teksti për të dërguar: ")
        \/\/ rresht pas rreshti
        text, err := reader.ReadString('n')
        if err != nil {
            log.Fatalln(err)
        }
        \/\/ dërgimi
        fmt.Fprintf(conn, text+"n")
        \/\/ marrja
        msg, err := bufio.NewReader(conn).ReadString('n')
        if err != nil {
            log.Fatalln(err)
        }
        \/\/ shfaqja e përgjigjes së marrë
        fmt.Print("Mesazhi nga Serveri: " + msg)
    }
}

Përfundimi

Mekanizmat që sigurojnë transmetimin e besueshëm të të dhënave dhe përdorimin e tyre

Mekanizmi
Përdorimi, komentimi

Kontrolli i shumës
Përdoret për të zbuluar gabimet në bitet e paketës së dërguar

Nënpërmjet këndit
Numërimi i intervalit të pritjes dhe tregimi i përfundimit të tij. E fundit do të thotë se me një probabilitet të lartë paketa ose konfirmimi i saj janë humbur gjatë dërgimit. Në rast se paketa arrin me vonesë, por nuk humbet (skadimi i parakohshëm i intervalit të pritjes), ose ndodh humbja e konfirmimit, ripaketimi çon në dublikimin e paketës në anën e marrësit

Numri rendor
Përdoret për numërimin rendor të paketave të dhënash të dërguara nga dërguesi te marrësi. Ndërprerjet në numrat rendor të paketave të marra lejojnë marrësin të zbulojë humbjen e paketës. Numrat rendor të barabartë të paketave nënkuptojnë se paketat dublikojnë njëra-tjetrën

Konfirmimi
Krijohet nga ana e marrësit dhe i tregon dërguesit se paketa ose grupi i paketave përkatëse janë pranuar me sukses. Zakonisht konfirmimi përmban numrat rendor të paketave të pranuara me sukses. Në varësi të protokollit, dallohen konfirmime individuale dhe grupore

Konfirmimi negativ
Përdoret nga marrësi për t'i njoftuar dërguesit se paketa është marrë gabim. Konfirmimi negativ zakonisht përfshin numrin rendor të paketës që nuk është marrë siç duhet

Dritarja, konvejimi
Kufizojnë gamën e numrave ordinal që mund të përdoren për transfertën e paketave. Transfertat në grup dhe dorëzimi lejojnë të rritet ndjeshëm kapaciteti i protokolleve krahasuar me modalitetin e pritjes për konfirmime. Siç do ta shohim, madhësia e dritares mund të llogaritet mbi baza të mundësive të pranimit dhe buferizimit të palës marrëse, si dhe nivelit të ngarkesës së rrjetit.

Shembuj të tjerë të përdorimit të Go për punë me rrjetin.

Në repotitë e tij.

Burimi: habr.com

Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Blini hosting tĂ« besueshĂ«m pĂ«r faqe interneti me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster