
Neile, kes soovivad mõista võrgustikke ja protokolle, on pühendatud.
Lühidalt
Artiklis käsitletakse andmete usaldusväärse edastamise aluseid, tuuakse näiteid , sealhulgas UDP ja TCP. Inspireerituna , , ja raamatust "Arvutivõrgud. Ülemineku lähenemine", kuna kõik räägivad ainult Tanenbaumist ja Oliferist.
Transpordiprotocol
Tagab loogilise ühenduse erinevates hostides toimivate rakendusprotsesside vahel. Rakenduste seisukohalt näeb loogiline ühendus välja nagu kanal, mis ühendab protsessid otse.

on toetatud lõpp-süsteemide poolt, kuid mitte võrgu marsruuterite poolt (välja arvatud — ). Saatja poolel muundab transpordikiht rakendustaseme andmed, mille ta saab edastamise rakenduse protsessilt, transporditaseme pakettideks, mida nimetatakse segmentideks.

See toimub rakendustaseme sõnumite vajadusel killustamise ja igale neist transporditaseme päise lisamise kaudu.

Seejärel edastab transpordikiht segmendi saatja võrgu kihile, kus segment kapseldatakse võrgu taseme paketti (datagrammi) ja saadetakse välja. Vastuvõtva poole võrgu kiht ekstraktib transporditaseme segmendi datagrammist ja edastab selle üles transporditasemele. Edasi töötleb transpordikiht saadud segmenti nii, et selle andmed muutuvad vastuvõtvale rakendusele kergesti kätte saadavaks.

Usaldusväärse andmeedastuse põhimõtted
Usaldusväärne andmeedastus täiesti usaldusväärses kanal
Lihtsaim juhtum. Saatja poolel võetakse andmed ülalt, luuakse nendes sisalduv pakett ja saadetakse see kanalisse.
Server
package main
import (
"log"
"net"
)
func main() {
// Serveri IP-aadress ja port
serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
if err != nil {
log.Fatal(err)
}
// Loo sokkel porti jaoks
serverConn, err := net.ListenUDP("udp", serverAddr)
if err != nil {
log.Fatal(err)
}
// Edasi lükatud ühenduse sulgemine
defer serverConn.Close()
// Loome andmepuhvri
buf := make([]byte, 1024)
// Ootame ühendust
for {
// Loeme päringut
n, addr, err := serverConn.ReadFromUDP(buf)
// Edastame andmed ÜLSEMISKIHTI: meie juhul stdout
println(string(buf[0:n]), " forma ", addr.IP.String())
if err != nil {
log.Fatal(err)
}
// Vastust ei ole, kuna see on UDP + usaldusväärne kanal
}
}Kliendi
package main
import (
"fmt"
"log"
"net"
"time"
)
func main() {
// Serveri IP-aadress ja port
serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
if err != nil {
log.Fatal(err)
}
// Kohalik IP-aadress ja port
localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
if err != nil {
log.Fatal(err)
}
// Ühenduse loomine
conn, err := net.DialUDP("udp", localAddr, serverAddr)
if err != nil {
log.Fatal(err)
}
// Edasi lükatud ühenduse sulgemine
defer conn.Close()
for {
// Andmete saamine ÜLSEMISKIHTILT
fmt.Print("Sisestage lause > ")
var msg string
_, err := fmt.Scanf("%s", &msg)
if err != nil {
log.Fatal(err)
}
// Edastatakse baitide voog, mitte string
buf := []byte(msg)
// Kirjutamine (edastamine) ühendusse
_, err = conn.Write(buf)
if err != nil {
log.Fatal(err)
}
// Üks sekund
time.Sleep(time.Second * 1)
}
}Usaldusväärne andmete edastus kanalilt, kus võivad esineda vead
Järgmine etapp on eeldus, et kõik edastatud paketid on saadud selles järjekorras, milles need saadeti, kuid nendes olevad bitid võivad olla kahjustatud, kuna kanal edastab andmeid mõnikord moonutustega.

Sellisel juhul rakendatakse mehhanisme:
- vea avastamine;
- tagasiside;
- uuesti edastus.
Usaldusväärsete andmete edastusprotokollid, mis sisaldavad sarnaseid korduva edastuse mehhanisme, nimetatakse automaatse kordusnõude (Automatic Repeat reQuest, ARQ) protokollideks.
Lisaks tuleks ette näha ka vigu ja vastuvõtjate kviitungites, kui vastuvõtja ei saa teavet viimase paketi edastamise tulemuste kohta.
Selle ülesande lahendus, mida kasutatakse ka TCP-s, seisneb andmepaketti uue välja lisamises, mis sisaldab paketi järjestuse numbrit.

Usaldusväärne andmete edastus usaldamatul kanalil, mis võimaldab moonutusi ja pakettide kadumist.
Kahjuks esinevad võrgu jooksul ka moonutused ja pakettide kaotus.
Ja selle probleemi lahendamiseks on vajalikud mehhanismid:
- pakettide kaotuse tuvastamine;
- kaotatud pakettide uuesti saatmine vastuvõtjale.
Lisaks pakettide kadumisele tuleb arvestada ka kinnituste kadumise võimalusega või, kui mitte midagi ei ole kadunud, selle edastamisega märkimisväärse viivitusega. Igale juhtumile järgneb sama tegevus: paketi kordussaatmine. Selle mehhanismi aja jälgimiseks kasutatakse tagasikutsumise taimerit, mis võimaldab määrata ooteintervalli lõppu. Nii et pakettides on TCPKeepAlive parameeter vaikimisi seatud 15 sekundiks:
// defaultTCPKeepAlive is a default constant value for TCPKeepAlive times
// See golang.org/issue/31510
const (
defaultTCPKeepAlive = 15 * time.Second
)Saatja peab käivitama taimeri iga kord paketi edastamisel (nii esmakordsel kui ka kordussaatmisel), töötlema taimerist saadud katkestusi ning peatama selle.
Nii oleme tutvunud usaldusväärse andmeedastuse protokollide põhikontseptsioonidega:
- kontrollsummad;
- pakettide järjekorranumbrid;
- taimerid;
- positiivsed ja negatiivsed kinnitused.
Aga see ei ole kõik!
Usaldusväärse andmeedastuse protokoll koos konveierimisega.
Käesolevas variandis, mida oleme juba vaadanud, on usaldusväärse edastamise protokoll väga ebatõhus. See hakkab viivitama edastust, mida toetab sidekanal, kui RTT suureneb. Selle tõhususe suurendamiseks ja sidekanali läbilaskevõime parema kasutuse jaoks rakendatakse konveierimist.

Konveierimise rakendamine toob kaasa:
- järjekorranumbrite piirkonna suurenemine, kuna kõik saadetavad paketid (välja arvatud korduvad edastused) peavad olema selgelt tuvastatavad;
- vajaduse suurendada mälupuhvrite mahtu saatja ja vastuvõtja poolel.
Järjekorranumbrite vahemik ja mälupuhvrite suuruse nõuded sõltuvad protokolli tegevustest vastusena moonutusele, pakettide kadumisele ja viivitusele. Konveierimise puhul on kaks vigade parandamise meetodit:
- tagasi N paketti;
- valikuline kordus.
Tagasi N paketti — libiseva akna protokoll.

Saatjal peab olema kolm tüüpi sündmusi:
- kõrgema taseme protokolli kutse. Kui "ülemine" tasand kutsub andmete saatmise funktsiooni, kontrollib saatja esmalt akna täituvust (st kas on olemas N saadetud sõnumit, mis ootavad kinnitusi). Kui aken ei ole täidetud, vormitakse ja edastatakse uus pakk, ning muutujate väärtused uuendatakse. Vastupidisel juhul tagastab saatja andmed ülemisele tasandile, mis on kaudne märk, et aken on täidetud. Tüüpiliselt ülemine tasand proovib andmete edastamist uuesti mõne aja pärast. Reaalses rakenduses oleks saatja tõenäoliselt kas andmeid vahemällu salvestanud (mitte kohe saatnud) või omanud sünkroniseerimise mehhanismi (näiteks semafori või lipu), mis võimaldaks ülemisel tasandil kutsuda andmete saatmise funktsiooni vaid siis, kui aken on tühi.
- kinnituse saamine. Protokollis antakse pakett, mille järjestuse number on N, üldine kinnitus, mis näitab, et kõik pakettide järjestuse numbrid, mis on ettepoole N, on edukalt vastu võetud.
- ootamisintervalli aegumine. Pakettide ja kinnituste kaotuste ning viivituste tuvastamiseks kasutab protokoll ajastusmeetrit. Kui ootamisintervall aegub, saadab saatja uuesti kõik saadetud kinnitamata paketid.
Valikuline kordamine
Kui akna suurus ja läbilaskevõime korrutatud leviaeg on suured, võib torus olla palju pakette. Sellisel juhul võib ühe paketi tõrge põhjustada paljude pakettide korduvate edastamiste, millest enamus ei olnud vajalikud.
Näide
Parimad praktikad on kokku kogutud praktilises rakendamises . Ja kui keegi teab, kuidas paremini — .
Server
package main
import (
"bufio"
"fmt"
"log"
"net"
"strings"
)
func main() {
// loome soketi sadama
ln, err := net.Listen("tcp", ":8081")
if err != nil {
log.Fatalln(err)
}
// ootame kutset
conn, _ := ln.Accept()
for {
// andmete lugemine
msg, err := bufio.NewReader(conn).ReadString('n')
if err != nil {
log.Fatalln(err)
}
// sõnumi väljund stdoutisse
fmt.Print("Sõnum vastu võetud:", string(msg))
// rea teisendamine suurte tähtedega
newMsg := strings.ToUpper(msg)
// andmete saatmine
conn.Write([]byte(newMsg + "n"))
}
}Kliendi
pakett põhjas
import (
"bufio"
"fmt"
"log"
"net"
"os"
)
func main() {
// ühenduse loomine
conn, err := net.Dial("tcp", "127.0.0.1:8081")
if err != nil {
log.Fatalln(err)
}
for {
// andmete lugemine stdin'ist
reader := bufio.NewReader(os.Stdin)
fmt.Print("Saadetav tekst: ")
// realt
text, err := reader.ReadString('n')
if err != nil {
log.Fatalln(err)
}
// saatmine
fmt.Fprintf(conn, text+"n")
// vastuvõtt
msg, err := bufio.NewReader(conn).ReadString('n')
if err != nil {
log.Fatalln(err)
}
// saadud vastuse kuvamine
fmt.Print("Serverilt sõnum: " + msg)
}
}Kokkuvõte
Mehhanismid, mis tagavad usaldusväärse andme edastamise ja nende kasutamise
Mehhanism
Rakendus, kommentaar
Kontrollsumma
Kasutatakse edastatud paketi bitivigade tuvastamiseks
Taimer
Ooteintervalli mõõtmine ja selle lõppemise näitamine. Viimane tähendab, et suure tõenäosusega on pakk või selle kinnitamine edastamisel kaotsi läinud. Kui pakk saabub viivitusega, kuid mitte kaduma (enneaegne ooteintervalli lõppemine), või toimub kinnitamise kadu, toob uuesti edastamine kaasa pakettide dubleerimise vastuvõtva poolel
Järjekorranumber
Kasutatakse andmepakettide järjekorranumbrite numeerimiseks, mis edastatakse saatjalt vastuvõtjale. Puudujäägid saadud pakettide järjekorranumbris võimaldavad vastuvõtjal tuvastada pakettide kadumise. Sama järjekorranumber tähendab, et paketid dubleerivad üksteist
Kinnitamine
Genereeritakse vastuvõtva poole poolt ja näitab edastava poolele, et vastav pakk või pakettide rühm on edukalt vastu võetud. Reeglina sisaldab kinnitamine edukalt vastu võetud pakettide järjekorranumbrid. Olenevalt protokollist eristatakse individuaalseid ja grupi kinnitusi
Negatiivne kinnitamine
Kasutakse vastuvõtja poolt saatjale teate edastamiseks, et pakk on saadud valesti. Negatiivne kinnitamine sisaldab tavaliselt järjekorranumbrit paketti, mis ei ole korrektselt saadud
Aken, konveierimine
Piiravad kindlate järjekorranumbrite vahemikku, mida saab pakkide edastamiseks kasutada. Grupiedastus ja käepigistus võimaldavad protokollide läbilaskevõimet märkimisväärselt suurendada võrreldes kinnituste ootamisrežiimiga. Nagu me näeme, saab akna suurust arvutada vastuvõtja poole vastuvõtu- ja vahemäluvõimekuse ning võrgu koormuse taseme põhjal.
Teised näited Go kasutamisest võrgu tööks.
Uues .
Allikas: habr.com
