Aan diegene wat
kortliks
Die artikel bespreek die basiese beginsels van betroubare data-oordrag, implementeer voorbeelde oor
Vervoerlaagprotokol
Verskaf 'n logiese verband tussen toepassingsprosesse wat op verskillende gashere loop. Vanuit 'n toepassingsperspektief lyk 'n logiese verband soos 'n kanaal wat prosesse direk verbind.
Dit word gedoen deur (indien nodig) die toepassingslaagboodskappe in fragmente te verdeel en 'n vervoerlaagopskrif by elkeen van hulle te voeg.
Die vervoerlaag gee dan die segment deur na die sender se netwerklaag, waar die segment in 'n netwerklaagpakkie (datagram) ingekapsuleer en gestuur word. Aan die ontvangkant onttrek die netwerklaag die vervoerlaagsegment uit die datagram en gee dit op na die vervoerlaag. Vervolgens verwerk die vervoerlaag die ontvangde segment sodat sy data beskikbaar word vir die ontvangende toepassing.
Beginsels van betroubare data-oordrag
Betroubare data-oordrag oor 'n heeltemal veilige kanaal
Die eenvoudigste geval. Die stuurkant ontvang eenvoudig die data van die boonste laag, skep 'n pakkie wat dit bevat en stuur dit na die kanaal.
Bediener
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 + надежный канал
}
}
kliënt
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)
}
}
Betroubare data-oordrag oor 'n kanaal met moontlike foute
Die volgende stap is om te aanvaar dat alle versendte pakkies ontvang word in die volgorde waarin hulle gestuur is, maar die stukkies daarin kan korrupteer wees as gevolg van die feit dat die kanaal soms data met vervormings oordra.
In hierdie geval word die volgende meganismes gebruik:
- foutopsporing;
- terugvoer;
- heruitsending.
Betroubare data-oordragprotokolle wat soortgelyke meganismes het om oordrag verskeie kere te herhaal, word Automatic Repeat ReQuest (ARQ)-protokolle genoem.
Daarbenewens is dit die moeite werd om die moontlikheid van foute in kwitansies te oorweeg, wanneer die ontvangende party geen inligting oor die resultate van die oordrag van die laaste pakkie sal ontvang nie.
Die oplossing vir hierdie probleem, wat ook in TCP gebruik word, is om 'n nuwe veld by die datapakkie te voeg wat die volgordenommer van die pakkie bevat.
Betroubare data-oordrag oor 'n onbetroubare kanaal onderhewig aan pakkievervorming en verlies
Saam met vervorming is daar ongelukkig pakkieverlies in die netwerk.
En om hierdie probleem op te los, is meganismes nodig:
- die bepaling van die feit van pakkieverlies;
- heraflewering van verlore pakkies aan die ontvangende party.
Benewens die verlies van die pakket, is dit nodig om voorsiening te maak vir die moontlikheid van verlies van die kwitansie of, indien niks verlore gaan nie, die aflewering daarvan met 'n aansienlike vertraging. In alle gevalle word dieselfde gedoen: die pakkie word weer versend. Om tyd te beheer, gebruik hierdie meganisme 'n afteltydhouer, wat jou toelaat om die einde van die waginterval te bepaal. So in die pakkie
// defaultTCPKeepAlive is a default constant value for TCPKeepAlive times
// See golang.org/issue/31510
const (
defaultTCPKeepAlive = 15 * time.Second
)
Die stuurkant moet 'n timer begin elke keer as 'n pakkie versend word (beide die eerste en die tweede keer), onderbrekings van die tydhouer hanteer en dit stop.
So, ons het vertroud geraak met die sleutelkonsepte van betroubare data-oordragprotokolle:
- kontrolesomme;
- volgordenommers van pakkette;
- timers;
- positiewe en negatiewe kwitansies.
Maar dit is nie al nie!
Betroubare data-oordragprotokol met pypleiding
In die variant wat ons reeds oorweeg het, is die betroubare afleweringsprotokol baie ondoeltreffend. Dit begin die transmissie wat deur die kommunikasiekanaal verskaf word "vertraag" soos die RTT toeneem. Om die doeltreffendheid daarvan te verhoog en die kommunikasiekanaalkapasiteit beter te benut, word pypleiding gebruik.
Die gebruik van pypleiding lei tot:
- verhoging van die reeks volgordenommers, aangesien alle gestuurde pakkies (behalwe vir heruitsendings) uniek geïdentifiseer moet word;
- die behoefte om buffers aan die stuur- en ontvangkant te verhoog.
Die reeksnommerreeks en buffergroottevereistes hang af van die aksies wat die protokol neem in reaksie op pakkiekorrupsie, verlies en vertraging. In die geval van pypleiding is daar twee metodes om foute reg te stel:
- stuur N pakkies terug;
- selektiewe herhaling.
Gaan terug N pakkies - gly venster protokol
Die sender moet drie tipes gebeurtenisse ondersteun:
- oproep deur 'n hoër vlak protokol. Wanneer die datastuurfunksie "van bo" genoem word, kontroleer die stuurkant eers die graad van vul van die venster (dit wil sê die teenwoordigheid van N gestuurde boodskappe wat wag op ontvangs van kwitansies). As die venster leeg is, word 'n nuwe pakkie gegenereer en versend, en die veranderlike waardes word opgedateer. Andersins stuur die stuurkant data terug na die boonste laag, en dit is 'n implisiete aanduiding dat die venster vol is. Tipies sal die boonste laag probeer om die data na 'n rukkie weer oor te dra. In 'n regte toepassing sal die sender waarskynlik óf die data buffer (in plaas daarvan om dit dadelik te stuur) óf 'n sinchronisasiemeganisme (soos 'n semafoor of vlag) hê wat die boonste laag sal toelaat om die stuurfunksie te roep slegs wanneer die venster leeg is .
- bevestiging ontvang. In die protokol, vir 'n pakkie met volgnommer N, word 'n algemene erkenning uitgereik wat aandui dat alle pakkies met volgnommers wat N voorafgaan, suksesvol ontvang is.
- die waginterval het verstryk. Om die feite van verliese en vertragings van pakkies en kwitansies te bepaal, gebruik die protokol 'n timer. As die uittelinterval verstryk, stuur die stuurkant alle gestuurde, nie-erkende pakkies weer.
Selektiewe herhaling
Wanneer die venstergrootte en die deurset-voortplantingsvertragingsproduk groot is, kan 'n groot aantal pakkies in die pyplyn wees. In so 'n geval kan 'n enkele pakkie fout veroorsaak dat 'n groot aantal pakkies herversend word, waarvan die meeste nie nodig was nie.
Voorbeeld
Top
Bediener
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"))
}
}
kliënt
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)
}
}
Output
Meganismes om betroubare data-oordrag en gebruik te verseker
meganisme
Aansoek, kommentaar
Kontroleer som
Word gebruik om bisfoute in 'n versendte pakkie op te spoor
Tydopnemer
Tel die uittelinterval af en dui aan wanneer dit verstryk het. Laasgenoemde beteken dat met 'n hoë mate van waarskynlikheid die pakkie of sy kwitansie verlore gaan tydens transmissie. As 'n pakkie met 'n vertraging afgelewer word, maar nie verlore gaan nie (voortydige verstryking van die uittelinterval), of 'n kwitansie verlore gaan, lei heruitsending tot 'n duplikaatpakkie aan die ontvangkant
Reeksnommer
Word gebruik vir opeenvolgende nommering van datapakkies wat van sender na ontvanger versend is. Leemtes in die volgordenommers van ontvangde pakkies laat die ontvanger toe om pakkieverlies op te spoor. Dieselfde pakkie volgorde nommers beteken dat die pakkies is duplikate van mekaar
Bevestiging
Gegenereer deur die ontvangkant en aandui aan die stuurkant dat die ooreenstemmende pakkie of groep pakkies suksesvol ontvang is. Tipies bevat die erkenning die volgordenommers van pakkies wat suksesvol ontvang is. Afhangende van die protokol, word individuele en groepbevestigings onderskei
Negatiewe bevestiging
Word deur die ontvanger gebruik om die sender in kennis te stel dat die pakkie verkeerd ontvang is. 'n Negatiewe erkenning sluit gewoonlik die volgnommer van die pakkie in wat nie korrek ontvang is nie
Venster, vervoer
Beperk die reeks rynommers wat gebruik kan word om pakkies te versend. Multicast en handdruk kan protokol deurset aansienlik verhoog in vergelyking met wag vir erkennings. Soos ons sal sien, kan die venstergrootte bereken word op grond van die ontvangs- en buffervermoë van die ontvangkant, sowel as die netwerkladingsvlak
Meer voorbeelde van die gebruik van Go vir netwerk
В
Bron: will.com