
Ji yên ku Ji bo têgihîştina toran û protokolan ve girêdayî ye.
Bi kurt
Gotar li ser bingehên ragihandina daneya pêbawer nîqaş dike, mînakan li ser bicîh tîne , tevî UDP û TCP. Çi qewimî , , û pirtûkên "Torên Kompîturê. Nêzîkatiya Ser-Ber jêr", wekî din her kes tenê Tannenbaum û Oliferov nîqaş dike.
Protokola qatê veguhastinê
Têkiliyek mentiqî di navbera pêvajoyên serîlêdanê yên ku li ser mêvandarên cihêreng têne xebitandin peyda dike. Ji perspektîfek serîlêdanê, pêwendiyek mentiqî mîna kanalek ku rasterast pêvajoyan girêdide xuya dike.

ji hêla pergalên dawîn ve têne piştgirî kirin, lê ne ji hêla routerên torê ve têne piştgirî kirin (ji bilî - ). Li aliyê şanderê, qatê veguheztinê daneya qata serîlêdanê ya ku ji pêvajoya sepana şandinê werdigire vediguherîne pakêtên qata veguheztinê ku jê re dibêjin beş.

Ev bi dabeşkirina (heke pêwîst be) peyamên qata serîlêdanê li perçeyan û lê zêdekirina sernavê qatek veguheztinê li her yekê ji wan pêk tê.

Dûv re qatê veguheztinê beşê di qata torê ya şanderê re derbas dike, li wir beş di pakêtek qata torê (datagram) de tê girtin û şandin. Di dawiya wergirtinê de, qata torê perçeya qata veguhastinê ji datagramê derdixe û wê berbi qata veguheztinê ve dibe. Dûv re, qata veguhastinê beşa wergirtî pêvajoyê dike da ku daneyên wê ji serîlêdana wergirtinê re peyda bibe.

Prensîbên ragihandina daneya pêbawer
Veguheztina daneya pêbawer li ser kanalek bi tevahî ewledar
Doza herî hêsan. Aliyê şandinê tenê daneyan ji qata jorîn distîne, pakêtek tê de diafirîne û ji kanalê re dişîne.
Server
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 + надежный канал
}
}Mişterî
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)
}
}Veguheztina daneya pêbawer li ser kanalek bi xeletiyên gengaz
Pêngava paşîn ev e ku meriv texmîn bike ku hemî pakêtên hatine veguheztin bi rêza ku ew hatine şandin têne wergirtin, lê dibe ku bit di wan de xera bibin ji ber vê yekê ku kanal carinan daneyan bi xeletiyan dişîne.

Di vê rewşê de, mekanîzmayên jêrîn têne bikaranîn:
- tespîtkirina çewtiyê;
- feedback;
- retransmission.
Protokolên veguheztina daneya pêbawer ên ku mekanîzmayên mîna wan hene ji bo dubarekirina veguheztinê pir caran jê re protokolên Dubarekirina Xweseriya ReQuest (ARQ) tê gotin.
Wekî din, hêja ye ku meriv îhtîmala xeletiyên di meqbûzan de were hesibandin, dema ku partiya wergir dê di derheqê encamên veguheztina pakêta paşîn de agahdarî negire.
Çareseriya vê pirsgirêkê, ku di TCP-ê de jî tê bikar anîn, ev e ku zeviyek nû li pakêta daneyê ya ku jimara rêza pakêtê vedihewîne zêde bike.

Veguheztina daneya pêbawer li ser kanalek nepêbawer ku ji ber xirabkirin û windabûna pakêtê ye
Digel tehlûkê, mixabin, di torê de windabûna pakêtê jî heye.
Û ji bo çareserkirina vê pirsgirêkê, mekanîzmayên hewce ne:
- diyarkirina rastiya windabûna pakêtê;
- ji nû ve radestkirina pakêtên windabûyî ji partiya wergir re.
Digel vê yekê, ji bilî windakirina pakêtê, pêdivî ye ku îhtîmala windabûna wergirtinê an jî, heke tiştek winda nebe, radestkirina wê bi derengiyek girîng were peyda kirin. Di hemû rewşan de, heman tişt tê kirin: pakêt ji nû ve tê şandin. Ji bo kontrolkirina demê, ev mekanîzma demjimêrek jimartinê bikar tîne, ku dihêle hûn dawiya navbera bendê diyar bikin. Ji ber vê yekê di pakêtê de TCPKeepAlive ji hêla xwerû ve li ser 15 saniyeyan hatiye danîn:
// defaultTCPKeepAlive is a default constant value for TCPKeepAlive times
// See golang.org/issue/31510
const (
defaultTCPKeepAlive = 15 * time.Second
)Aliyê şandinê pêdivî ye ku her gava ku pakêtek tê veguheztin (hem gava yekem û hem jî ya duyemîn) demjimêrek dest pê bike, qutkirina demjimêran bigire û wê rawestîne.
Ji ber vê yekê, me bi têgehên sereke yên protokolên veguheztina daneya pêbawer re nas kir:
- checksums;
- jimareyên rêzê yên pakêtan;
- timers;
- wergirtinên erênî û neyînî.
Lê ev ne hemû ye!
Protokola veguheztina daneya pêbawer bi pipelining
Di guhertoya ku me berê jî fikirî de, protokola radestkirina pêbawer pir bêbandor e. Gava ku RTT zêde dibe, ew dest bi "hêdî" dike ku veguheztina ku ji hêla kanala ragihandinê ve hatî peyda kirin. Ji bo zêdekirina karbidestiya wê û çêtir karanîna kapasîteya kanala danûstendinê, pipelining tê bikar anîn.

Bikaranîna pipelining dibe sedema:
- zêdekirina rêza hejmarên rêzikan, ji ber ku hemî pakêtên hatine şandin (ji bilî veguheztinan) divê yekta bêne nas kirin;
- hewcedariya zêdekirina tamponan li aliyên veguhezkar û wergirtinê.
Rêzeya jimareya rêzê û hewcedariyên mezinahiya tamponê bi kiryarên ku protokol di bersivdayîna gendeliyê, windakirin û derengiya pakêtê de digire ve girêdayî ye. Di mijara boriyê de, du awayên rastkirina xeletiyan hene:
- N pakêtan vegerîne;
- dubarekirina hilbijartî.
Vegera N pakêtên - protokola pencereya sliding

Divê şander sê celeb bûyeran piştgirî bike:
- bi protokolek astek bilindtir bang bikin. Gava ku fonksiyona şandina daneyê "ji jor ve" tê gotin, aliyê şandinê pêşî asta dagirtina pencereyê kontrol dike (ango hebûna N peyamên şandine li benda wergirtina wergirtinê). Ger pace vala be, pakêtek nû tê çêkirin û şandin, û nirxên guhêrbar têne nûve kirin. Wekî din, alîyê şandinê daneyan vedigerîne qata jorîn, û ev nîşanek nepenî ye ku pencere tije ye. Bi gelemperî qata jorîn dê piştî demek şûnde hewl bide ku daneyan veguhezîne. Di serîlêdanek rastîn de, şander îhtîmal e ku daneyan tampon bike (li şûna ku wê tavilê bişîne) an jî mekanîzmayek hevdengkirinê hebe (mîna semaforek an ala) ku destûrê dide tebeqeya jorîn ku fonksiyona şandinê tenê dema ku pencere vala ye bang bike. .
- wergirtina pejirandinê. Di protokolê de, ji bo pakêtek bi rêza jimareya N, pejirandinek giştî tê derxistin ku destnîşan dike ku hemî pakêtên bi jimareya rêza li pêş N bi serfirazî hatine wergirtin.
- navbera bendewariyê bi dawî bûye. Ji bo destnîşankirina rastiyên windabûn û derengiya pakêt û wergirtinê, protokol demjimêrek bikar tîne. Heger navbera wextê bi dawî bibe, aliyê şandî hemû pakêtên ku nehatine şandin ji nû ve dişîne.
Dubarekirina hilbijartî
Dema ku mezinahiya pencereyê û hilbera derengiya berbelavbûnê mezin be, dibe ku hejmareke mezin ji pakêtan di boriyê de bin. Di rewşek weha de, xeletiyek yek pakêtê dibe ku bibe sedem ku hejmareke mezin ji pakêtan ji nû ve werin veguheztin, ku piraniya wan ne hewce bûn.
Nimûne:
Baştirîn pratîk di pêkanîna pratîk de têne berhev kirin . Û heger kesek dizane ka çiqas çêtirîn - .
Server
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"))
}
}Mişterî
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)
}
}encamê
Mekanîzmayên ku ji bo veguheztin û karanîna daneya pêbawer piştrast dikin
Mîkrozîzmê
Serlêdan, şîrove
Berhevokê kontrol bikin
Ji bo tesbîtkirina xeletiyên bit di pakêtek veguhestî de tê bikar anîn
Demjimêr
Navbera wextê bihejmêre û kengê qediya nîşan dide. Ya paşîn tê vê wateyê ku bi îhtimalek mezin pakêt an jî wergirtina wê di dema veguheztinê de winda dibe. Ger paketek bi dereng were radest kirin, lê winda nebe (bidawîbûna zû ya navberê), an meqbûzek winda bibe, ji nû ve veguheztin dibe sedema pakêtek ducar li aliyê wergirtinê.
Xwarinên lezok
Ji bo jimareya rêzî ya pakêtên daneyê yên ku ji şander ji wergir re têne veguheztin tê bikar anîn. Valahiyên di hejmarên rêza pakêtên wergirtinê de dihêle ku wergir windabûna pakêtê bibîne. Heman hejmarên rêza pakêtê tê vê wateyê ku pakêt kopiyên hev in
Pejirandin
Ji hêla dawiya wergirtinê ve hatî çêkirin û ji dawiya şandinê re destnîşan dike ku pakêt an koma pakêtan bi serfirazî hatî wergirtin. Bi gelemperî pejirandin hejmarên rêzikên pakêtên ku bi serfirazî hatine wergirtin dihewîne. Li ser protokolê ve girêdayî, pejirandinên kesane û koman têne cûda kirin
Piştrastkirina neyînî
Ji hêla wergir ve tê bikar anîn da ku şanderê agahdar bike ku pakêt bi xeletî hatî wergirtin. Pejirandina negatîf bi gelemperî jimareya rêza pakêtê ya ku rast nehatiye wergirtin vedihewîne
Pencere, veguheztin
Rêjeya hejmarên rêzikan ên ku ji bo şandina pakêtan têne bikar anîn sînordar bikin. Multicast û handshake dikare li gorî benda pejirandinê bi girîngî rêgeza protokolê zêde bike. Wekî ku em ê bibînin, mezinahiya pencereyê dikare li ser bingeha kapasîteyên wergirtin û tamponkirina dawiya wergirtinê, û her weha asta barkirina torê were hesibandin.
Zêdetir mînakên karanîna Go ji bo torê
В .
Source: www.habr.com
