Кимдерге
кыскача
Макалада ишенимдүү маалыматтарды берүү негиздери талкууланат, боюнча мисалдар ишке ашырылат
Транспорт катмарынын протоколу
Ар кандай хосттордо иштеген колдонмо процесстеринин ортосундагы логикалык байланышты камсыздайт. Колдонмо көз карашынан алганда, логикалык байланыш процесстерди түз байланыштырган каналга окшош.
Бул колдонмо катмарынын билдирүүлөрүн фрагменттерге бөлүү (зарыл болсо) жана алардын ар бирине транспорттук катмардын башын кошуу менен ишке ашырылат.
Андан кийин транспорттук катмар сегментти жөнөтүүчүнүн тармактык катмарына өткөрөт, ал жерде сегмент тармактык катмар пакетине (датаграммага) капсулдалат жана жөнөтүлөт. Кабыл алуу жагында тармактык катмар датаграммадан транспорттук катмар сегментин чыгарып, аны транспорттук катмарга өткөрүп берет. Андан кийин транспорттук катмар кабыл алынган сегментти иштетет, ошондуктан анын маалыматтары кабыл алуучу колдонмого жеткиликтүү болот.
Ишенимдүү маалыматтарды берүү принциптери
Толугу менен коопсуз канал аркылуу ишенимдүү маалымат берүү
Эң жөнөкөй окуя. Жөнөтүүчү тарап үстүнкү катмардан маалыматтарды кабыл алып, аны камтыган пакетти түзүп, каналга жөнөтөт.
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 + надежный канал
}
}
кардар
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)
}
}
Мүмкүн болгон каталар менен канал боюнча ишенимдүү маалыматтарды берүү
Кийинки кадам - бардык берилген пакеттер алар жөнөтүлгөн тартипте кабыл алынат, бирок канал кээде маалыматтарды бурмалоо менен өткөрүп бергендиктен, андагы биттер бузулушу мүмкүн.
Бул учурда, төмөнкү механизмдер колдонулат:
- катаны аныктоо;
- пикир;
- кайра жөнөтүү.
Бир нече жолу кайталап берүүнүн окшош механизмдери бар ишенимдүү маалыматтарды берүү протоколдору Automatic Repeat ReQuest (ARQ) протоколдору деп аталат.
Кошумча, алуучу тарап акыркы пакетти өткөрүп берүүнүн натыйжалары жөнүндө эч кандай маалымат ала албай калганда, дүмүрчөктөрдөгү каталар ыктымалдыгын эске алуу зарыл.
Бул маселени чечүү, ошондой эле TCP колдонулат, пакеттин катар номерин камтыган маалымат пакетине жаңы талаа кошуу болуп саналат.
Пакеттин бузулушуна жана жоголушуна дуушар болгон ишенимсиз канал аркылуу маалыматтарды ишенимдүү берүү
Бурмалоо менен бирге, тилекке каршы, тармакта пакеттик жоготуулар бар.
Жана бул маселени чечүү үчүн механизмдер талап кылынат:
- пакетти жоготуу фактысын аныктоо;
- жоголгон пакеттерди кабыл алуучу тарапка кайра жеткирүү.
Кошумчалай кетсек, пакеттин жоголушунан тышкары, квитанцияны жоготуу мүмкүнчүлүгүн же эч нерсе жоголбосо, аны олуттуу кечигип жеткирүү мүмкүнчүлүгүн караштыруу зарыл. Бардык учурларда, бир эле нерсе жасалат: пакет кайра жөнөтүлөт. Убакытты көзөмөлдөө үчүн бул механизм күтүү интервалынын соңун аныктоого мүмкүндүк берген артка санак таймерин колдонот. Ошентип, пакетте
// defaultTCPKeepAlive is a default constant value for TCPKeepAlive times
// See golang.org/issue/31510
const (
defaultTCPKeepAlive = 15 * time.Second
)
Жөнөтүүчү тарап таймерди пакет жөнөтүлгөн сайын (биринчи жана экинчи жолу да) иштетип, таймерден үзгүлтүккө учурашы жана аны токтотушу керек.
Ошентип, биз ишенимдүү маалыматтарды берүү протоколдорунун негизги түшүнүктөрү менен таанышып калдык:
- текшерүү суммасы;
- пакеттердин катар номерлери;
- таймерлер;
- оң жана терс түшүүлөр.
Бирок бул баары эмес!
Түтүк өткөргүч менен ишенимдүү маалыматтарды берүү протоколу
Биз карап чыккан вариантта ишенимдүү жеткирүү протоколу абдан натыйжасыз. Ал RTT көбөйгөн сайын байланыш каналы тарабынан берилүүчү берүүнү "басаңдата" баштайт. Анын натыйжалуулугун жогорулатуу жана байланыш каналынын кубаттуулугун жакшыраак пайдалануу үчүн трубопровод колдонулат.
Түтүктөрдү колдонуу төмөнкүлөргө алып келет:
- катар номерлеринин диапазонун көбөйтүү, анткени бардык жөнөтүлгөн пакеттер (ретрансляциялардан башкасы) уникалдуу идентификацияланышы керек;
- берүү жана кабыл алуу жагындагы буферлерди көбөйтүү зарылчылыгы.
Тартиптик номер диапазону жана буфер өлчөмүнө талаптар пакеттин бузулушуна, жоголушуна жана кечигүүсүнө жооп катары протоколдун жасаган иш-аракеттеринен көз каранды. Түтүктөрдү өткөрүүдө каталарды оңдоонун эки ыкмасы бар:
- N пакетти кайра кайтаруу;
- тандалма кайталоо.
N пакеттерге артка кайтуу - жылма терезе протоколу
Жөнөтүүчү окуялардын үч түрүн колдоого тийиш:
- жогорку деңгээлдеги протокол менен чалуу. Маалыматтарды жөнөтүү функциясы "жогорудан" деп аталганда, жөнөтүүчү тарап алгач терезенин толтуруу даражасын текшерет (башкача айтканда, квитанцияларды алууну күткөн N жөнөтүлгөн билдирүүлөрдүн болушу). Терезе бош болсо, жаңы пакет түзүлөт жана өткөрүлүп берилет, ал эми өзгөрмө маанилери жаңыртылат. Болбосо, жөнөтүүчү тарап маалыматтарды үстүнкү катмарга кайтарат жана бул терезе толгондугунун кыйыр белгиси. Адатта, үстүнкү катмар бир нече убакыттан кийин маалыматтарды кайра берүүгө аракет кылат. Чыныгы тиркемеде жөнөтүүчү, кыязы, берилиштерди буферлейт (аны дароо жөнөтүүнүн ордуна) же синхрондоштуруу механизмине (мисалы, семафор же желекче) ээ болушу мүмкүн, ал терезе бош болгондо гана жогорку катмарга жөнөтүү функциясын чакырууга мүмкүндүк берет. .
- тастыктоо алуу. Протоколдо N ырааттуулугу бар пакет үчүн 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"))
}
}
кардар
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)
}
}
жыйынтыктоо
Ишенимдүү маалыматтарды берүүнү жана колдонууну камсыз кылуу механизмдери
механизм
Арыз, комментарий
текшерүү суммасы
Берилген пакеттеги бит каталарын аныктоо үчүн колдонулат
таймер
Тайм-аут аралыгын санайт жана анын качан бүткөнүн көрсөтөт. Акыркысы берүү учурунда пакеттин же анын дүмүрчөгүнүн жоголуп кетиши ыктымалдыгын билдирет. Эгерде пакет кечигүү менен жеткирилсе, бирок жоголбосо (тайм-аут аралыгы мөөнөтүнөн мурда бүтсө) же дүмүрчөк жоголсо, кайра жөнөтүү кабыл алуучу тарапта кайталанган пакетке алып келет.
Сериялык саны
Жөнөтүүчүдөн алуучуга берилүүчү маалымат пакеттерин ырааттуу номерлөө үчүн колдонулат. Кабыл алынган пакеттердин катар номерлериндеги боштуктар кабыл алуучуга пакеттин жоголушун аныктоого мүмкүндүк берет. Ошол эле пакеттердин ырааттуулугу пакеттердин бири-биринин дубликаттары экенин билдирет
ырастоо
Кабыл алуучу тарабынан түзүлгөн жана жөнөтүүчү тарапка тиешелүү пакет же пакеттердин тобу ийгиликтүү кабыл алынганын көрсөтүүчү. Адатта, ырастоо ийгиликтүү кабыл алынган пакеттердин катар номерлерин камтыйт. Протоколго жараша жеке жана топтук ырастоолор бөлүнөт
Терс ырастоо
Пакет туура эмес кабыл алынганын жөнөтүүчүгө билдирүү үчүн алуучу тарабынан колдонулат. Терс ырастоо, адатта, туура эмес кабыл алынган пакеттин катар номерин камтыйт
Терезе, конвейеризация
Пакеттерди өткөрүү үчүн колдонула турган катар номерлеринин диапазонун чектеңиз. Multicast жана кол алышуу ырастоолорду күтүүгө салыштырмалуу протоколдун өткөрүү жөндөмдүүлүгүн кыйла жогорулата алат. Көрүнүп тургандай, терезенин өлчөмүн кабыл алуучу тараптын кабыл алуу жана буферлөө мүмкүнчүлүктөрүнө, ошондой эле тармак жүктөө деңгээлине жараша эсептесе болот.
Тармак үчүн Go колдонуунун көбүрөөк мисалдары
Source: www.habr.com