
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
