
Bütün bunlar həsr olunur.
Qısa
Məqalədə məlumatın etibarlı ötürülməsinin əsasları müzakirə olunur, o cümlədən , UDP və TCP üzrə nümunələr təqdim olunur. Mündəricat , , və "Kompyuter Şəbəkələri. En tərtib" kitabından, çünki hamı yalnız Tanenbaum və Olifer haqqında danışır.
Nəqliyyat protokolu
Müxtəlif ev sahibində işləyən tətbiqi proseslər arasında məntiqi əlaqə təmin edir. Tətbiqlər baxımından məntiqi əlaqə, prosesi birbaşa birləşdirən kanal olaraq görünür.

son sistemlər tərəfindən dəstəklənir, lakin şəbəkə yönlendiriciləri tərəfindən (istisna ilə — ). Göndərən tərəfdə, nəqliyyat səviyyəsi tətbiqi səviyyədən aldığı məlumatları, göndərən tətbiqi prosesdən gələn paketlərə çevirmək üçün istifadə olunur.

Bu, tətbiqi səviyyə mesajlarının fraksiyalara bölünməsi (lazım olduqda) və hər birinə nəqliyyat səviyyəsi başlığı əlavə etməklə həyata keçirilir.

Daha sonra, nəqliyyat səviyyəsi segmenti göndərənin şəbəkə səviyyəsinə ötürür, burada segment, şəbəkə səviyyəsi paketi (datagram) içində kapsülləşdirilir və göndərilir. Qəbul edən tərəfdə, şəbəkə səviyyəsi, datagramdan nəqliyyat səviyyəsi segmentini çıxarıb onu yuxarı nəqliyyat səviyyəsinə ötürür. Sonra, nəqliyyat səviyyəsi alınan segmenti emal edərək onun məlumatlarını qəbul edən tətbiqə təqdim edir.

Məlumatın etibarlı ötürülməsi prinsipləri
Tam etibarlı kanaldan etibarlı məlumatların ötürülməsi
Ən sadə hal. Göndərən tərəf, yuxarı səviyyədən məlumatları qəbul edir, onları özündə saxlayan paketi yaradır və kanala göndərir.
Server
package main
import (
"log"
"net"
)
func main() {
// Serverin IP ünvanı və portu
serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
if err != nil {
log.Fatal(err)
}
// portu olan soket yaradırıq
serverConn, err := net.ListenUDP("udp", serverAddr)
if err != nil {
log.Fatal(err)
}
// əlaqəni bağlamaq üçün gözləmə
defer serverConn.Close()
// məlumatlar üçün tampon yaradırıq
buf := make([]byte, 1024)
// bağlantını gözləyirik
for {
// sorğunu oxuyuruq
n, addr, err := serverConn.ReadFromUDP(buf)
// məlumatları YUXARI səviyyəyə ötürürük: bizdə stdout-a
println(string(buf[0:n]), " form ", addr.IP.String())
if err != nil {
log.Fatal(err)
}
// cavab yoxdur, çünki bu UDP + etibarlı kanal
}
}Müştəri
package main
import (
"fmt"
"log"
"net"
"time"
)
func main() {
// Server IP address and port
serverAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:12000")
if err != nil {
log.Fatal(err)
}
// Local IP address and port
localAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
if err != nil {
log.Fatal(err)
}
// Establishing connection
conn, err := net.DialUDP("udp", localAddr, serverAddr)
if err != nil {
log.Fatal(err)
}
// Deferred connection close
defer conn.Close()
for {
// Receiving data from the upper layer
fmt.Print("Köhnə cümlə daxil edin > ")
var msg string
_, err := fmt.Scanf("%s", &msg)
if err != nil {
log.Fatal(err)
}
// A stream of bytes is transmitted, not a string
buf := []byte(msg)
// Writing (transmitting) to the connection
_, err = conn.Write(buf)
if err != nil {
log.Fatal(err)
}
// One second wait
time.Sleep(time.Second * 1)
}
}Etibarlı məlumat ötürülməsi mümkün olan xətalarla kanaldan
Növbəti mərhələdə, ötürülən bütün paketlərin göndərildiyi sırada alınacağı fikri qəbul edilir, lakin içindəki bitlər zədələnə bilər, çünki kanal bəzən məlumatları yüksək şəkildə ötürülə bilər.

Belə olan halda, aşağıdakı mexanizmlər tətbiq olunur:
- xətanın aşkarlanması;
- geri bildirim;
- təkrar ötürmə.
Belə mexanizmlərə malik etibarlı məlumat ötürmə protokolları, avtomatik təkrar sorğu protokolları (Automatic Repeat reQuest, ARQ) adlanır.
Həmçinin, qəbul edən tərəfin son paket ötürməsinin nəticələri barədə heç bir məlumat almadığı halında, təsdiqlərdə də xətaların baş verməsini nəzərə almaq lazımdır.
Bu məsələnin həlli, o cümlədən TCP-də, paket məlumatlarına yeni bir sahənin əlavə olunmasından ibarətdir ki, bu da paketlərin sıralama nömrəsini ehtiva edir.

Zədələnmə və paket itkisinin baş verməsini qəbul edən etibarlı məlumat ötürülməsi üçün
Təəssüf ki, zədələnmə ilə yanaşı, şəbəkədə paket itkisi də mövcuddur.
Və bu məsələnin həlli üçün aşağıdakı mexanizmlərin olması tələb olunur:
- paket itkisinin aşkar edilməsi;
- itirilmiş paketlərin qəbul edən tərəfə yenidən ötürülməsi.
Həmçinin, paket itkisi ilə yanaşı, təsdiqlərin itirilməsi və ya heç bir şey itirilmədiyində, onun keçirilməsində əhəmiyyətli gecikmə olması ehtimalını nəzərə almaq lazımdır. Hər vəziyyətdə eyni şey edilir: paketin yenidən ötürülməsi. Bu mexanizmin müddətini kontrol etmək üçün gözləmə intervalının bitməsini müəyyən etməyə imkan verən sayğac zamanı istifadə olunur. Belə ki, paket TCPKeepAlive parametri, standart olaraq 15 saniyə olaraq təyin olunub:
// defaultTCPKeepAlive is a default constant value for TCPKeepAlive times
// See golang.org/issue/31510
const (
defaultTCPKeepAlive = 15 * time.Second
)Göstərən tərəf hər dəfə paket ötürdükdə (ilk və təkrar daxil olmaqla) sayğacı işə salmalı, sayğacdan kəsilmələri ələ almalı və onu dayandırmalıdır.
Beləliklə, etibarlı məlumat ötürmə protokollarının əsas anlayışları ilə tanış olduq:
- nəzarət cəmi;
- paketlərin ardıcıl nömrələri;
- zamanlayıcılar;
- müsbət və mənfi təsdiqlər.
Amma bu, hələ hamısı deyil!
Verilənlərin etibarlı ötürülməsi protokolu ilə boru kəmərləşmə
Artıq müzakirə etdiyimiz variantda, etibarlı çatdırılma protokolu çox effektiv deyil. O, RTT artdıqca məlumatların ötürülməsi üçün təchiz edilmiş kanalda «dayanmağa» başlayır. Onun effektivliyini artırmaq, kanalın tutumunun daha yaxşı istifadəsi üçün boru kəmərləşmə tətbiq olunur.

Boru kəmərləşmənin tətbiqi aşağıdakı nəticələri gətirir:
- ardıcıl nömrələrin diapazonunun genişlənməsi, çünki bütün göndərilən paketlər (təkrarlanan ötürmələr istisna olmaqla) unikal şəkildə tanınmalıdır;
- göndərən və qəbul edən tərəflərdə tamponların artırılması ehtiyacı.
Ardıcıl nömrələrin diapazonu və tampon ölçüləri ilə bağlı tələblər, protokolun paketlərin pozulmasına, itirilməsinə və gecikməsinə cavab olaraq apardığı fəaliyyətlərdən asılıdır. Boru kəmərləşmə vəziyyətində iki səhv düzəltmə metodu mövcuddur:
- N paketi geri qaytarılması;
- seçici təkrar.
N paketi geri qaytarılması - sürüşən pəncərə protokolu

Göndərən üç növ hadisəni saxlamalıdır:
- yuxarı səviyyə protokolu ilə çağırış. Yuxarıdan data göndərmə funksiyası çağırıldıqda, göndərən tərəf əvvəlcə pəncərənin doldurulma dərəcəsini yoxlayır (yəni təsdiq gözləyən N göndərilmiş mesajın olub olmadığını). Əgər pəncəre boşdursa, yeni paket formalaşır və göndərilir, bununla yanaşı dəyişənlərin dəyərləri yenilənir. Əks halda, göndərən tərəf məlumatları yuxarı səviyyəyə qaytarır və bu, pəncərenin doldurulduğuna dair qeyri-müəyyən bir göstərişdir. Adətən, yuxarı səviyyə müəyyən bir müddətdən sonra məlumatların təkrar göndərilməsi üçün cəhdlər edir. Gerçək tətbiqdə göndərən, çox güman ki, ya məlumatları tamponlaşdırır (tez bir zamanda göndərmək əvəzinə), ya da yuxarı səviyyənin yalnız boş pəncərə olduqda göndərmə funksiyasını çağırmasına imkan verən bir sinxronizasiya mexanizminə (məsələn, semaphore və ya bayraq) malik olardı.
- təsdiq alınması. Protokolda N ardıcıl nömrəli paket üçün, N-dən əvvəlki bütün ardıcıl nömrələrə müvəffəqiyyətlə qəbul edildiyini göstərən ümumi təsdiq verilir.
- gözləmə müddətinin bitməsi. Paketlərin və təsdiqlərin itirilməsi və gecikmələri faktlarını müəyyənləşdirmək üçün protokol zamanlayıcı istifadə edir. Əgər gözləmə müddəti başa çatırsa, göndərən tərəf bütün göndərilmiş təsdiq olunmamış paketləri yenidən göndərir.
seçici təkrar
Pəncərə ölçüsü və gecikmə zamanı bant genişliyi böyük olduqda, boru kəmərində çox sayda paket ola bilər. Bu halda, bir paketin xətası, lazım olmayan çox sayda paketin yenidən göndərilməsinə səbəb ola bilər.
Məsələn
Ən yaxşı təcrübələr praktiki icra ilə toplanmışdır . Və kiminsə daha yaxşı bildiyi halda - .
Server
package main
import (
"bufio"
"fmt"
"log"
"net"
"strings"
)
func main() {
// bağlantı portu ilə soket yaradır
ln, err := net.Listen("tcp", ":8081")
if err != nil {
log.Fatalln(err)
}
// zəng gözləyir
conn, _ := ln.Accept()
for {
// məlumatları oxuyur
msg, err := bufio.NewReader(conn).ReadString('n')
if err != nil {
log.Fatalln(err)
}
// mesajı stdout-a çıxarır
fmt.Print("Göndərilən Mesaj:", string(msg))
// sətiri böyük hərflə yazır
newMsg := strings.ToUpper(msg)
// məlumatı göndərir
conn.Write([]byte(newMsg + "n"))
}
}Müştəri
package main
import (
"bufio"
"fmt"
"log"
"net"
"os"
)
func main() {
// bağlantı qurur
conn, err := net.Dial("tcp", "127.0.0.1:8081")
if err != nil {
log.Fatalln(err)
}
for {
// stdin-dən məlumatları oxuyur
reader := bufio.NewReader(os.Stdin)
fmt.Print("Göndəriləcək mətn: ")
// sətir-sətir
text, err := reader.ReadString('n')
if err != nil {
log.Fatalln(err)
}
// göndərir
fmt.Fprintf(conn, text+"n")
// qəbul edir
msg, err := bufio.NewReader(conn).ReadString('n')
if err != nil {
log.Fatalln(err)
}
// alınan cavabı çıxarır
fmt.Print("Serverdən Mesaj: " + msg)
}
}Çıktı
Məlumatların etibarlı ötürülməsini təmin edən mexanizm və onların istifadəsi
Mexanizm
Tətbiq, şərh
Kontrol cəmi
Göndərilmiş paketdə bit həta aşkar etmək üçün istifadə olunur
Taymer
Gözləmə müddətinin sayımı və onun bitməsinin göstəricisi. Bu, paket və ya onun təsdiqi ötürülmə zamanı yüksək ehtimalla itirilib deməkdir. Paket gecikmə ilə çatdırılsa da, itirilmiş təsdiq halında, yenidən göndərmə qəbul edən tərəfdə paketlərin çoxalmasına səbəb olur.
Sıra nömrəsi
Göndərən tərəfdən qəbul edəyənə ötürülən məlumat paketlərinin sıra nömrəsini təmin etmək üçün istifadə olunur. Qəbul edilən paketlərdəki sıralama nömrələrindəki boşluqlar, qəbul edənin paket itkisinin olduğunu aşkar etməyə imkan tanıyır. Eyni sıra nömrələrinə malik paketlər, paketlərin bir-birini təkrarladığını göstərir.
Təsdiq
Qəbul edən tərəf tərəfindən yaradılır və göndərən tərəfə müvafiq paketlərin və ya paket qruplarının uğurla qəbul edildiyini bildirir. Adətən, təsdiq uğurla qəbul edilən paketlərin sıra nömrələrini ehtiva edir. Protokoldan asılı olaraq fərdi və qruplaşdırılmış təsdiqlər arasında fərq var.
Müsbət təsdiq
Alıcının göndericiye paketin hatalı alındığını bildirmek için kullandığı bir yöntemdir. Olumsuz onay genellikle hatalı alınan paketin sıralı numarasını içerir.
Pencere, boru hattı
Paket aktarımı için kullanılabilecek sıralı numaraların aralığını sınırlayan unsurlardır. Gruplu aktarım ve el sıkışma, onay bekleme moduna göre protokollerin bant genişliğini önemli ölçüde artırabilir. Gördüğümüz gibi, pencere boyutu, alıcı tarafın kabul etme ve tamponlama yetenekleri ile ağın yükleme seviyesine dayanarak hesaplanabilir.
Ağ ile çalışmak için Go'nun diğer kullanım örnekleri
İ .
Mənbə: habr.com
