Ишенимдүү маалыматтарды берүүнүн негиздери

Ишенимдүү маалыматтарды берүүнүн негиздери

Кимдерге максат Тармактарды жана протоколдорду түшүнүүгө арналган.

кыскача

Макалада ишенимдүү маалыматтарды берүү негиздери талкууланат, боюнча мисалдар ишке ашырылат Go, анын ичинде UDP жана TCP. Негизинде убакыт, два, үч жана китептери "Компьютердик тармактар. Жогортон ылдый мамиле", антпесе баары Танненбаум менен Олиферовду гана талкуулап жатышат.

Транспорт катмарынын протоколу

Ар кандай хосттордо иштеген колдонмо процесстеринин ортосундагы логикалык байланышты камсыздайт. Колдонмо көз карашынан алганда, логикалык байланыш процесстерди түз байланыштырган каналга окшош.

Ишенимдүү маалыматтарды берүүнүн негиздери

Транспорт катмарынын протоколдору акыркы системалар тарабынан колдоого алынат, бирок тармак роутерлор тарабынан колдоого алынбайт (башкалары - DPI). Жөнөтүүчү тарапта транспорттук катмар жөнөтүүчү тиркеме процессинен алган колдонмо катмарынын маалыматтарын сегменттер деп аталган транспорттук катмар пакеттерине айлантат.

Ишенимдүү маалыматтарды берүүнүн негиздери

Бул колдонмо катмарынын билдирүүлөрүн фрагменттерге бөлүү (зарыл болсо) жана алардын ар бирине транспорттук катмардын башын кошуу менен ишке ашырылат.

Ишенимдүү маалыматтарды берүүнүн негиздери

Андан кийин транспорттук катмар сегментти жөнөтүүчүнүн тармактык катмарына өткөрөт, ал жерде сегмент тармактык катмар пакетине (датаграммага) капсулдалат жана жөнөтүлөт. Кабыл алуу жагында тармактык катмар датаграммадан транспорттук катмар сегментин чыгарып, аны транспорттук катмарга өткөрүп берет. Андан кийин транспорттук катмар кабыл алынган сегментти иштетет, ошондуктан анын маалыматтары кабыл алуучу колдонмого жеткиликтүү болот.

Ишенимдүү маалыматтарды берүүнүн негиздери

Ишенимдүү маалыматтарды берүү принциптери

Толугу менен коопсуз канал аркылуу ишенимдүү маалымат берүү

Эң жөнөкөй окуя. Жөнөтүүчү тарап үстүнкү катмардан маалыматтарды кабыл алып, аны камтыган пакетти түзүп, каналга жөнөтөт.

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 колдонулат, пакеттин катар номерин камтыган маалымат пакетине жаңы талаа кошуу болуп саналат.

Ишенимдүү маалыматтарды берүүнүн негиздери

Пакеттин бузулушуна жана жоголушуна дуушар болгон ишенимсиз канал аркылуу маалыматтарды ишенимдүү берүү

Бурмалоо менен бирге, тилекке каршы, тармакта пакеттик жоготуулар бар.
Жана бул маселени чечүү үчүн механизмдер талап кылынат:

  • пакетти жоготуу фактысын аныктоо;
  • жоголгон пакеттерди кабыл алуучу тарапка кайра жеткирүү.

Кошумчалай кетсек, пакеттин жоголушунан тышкары, квитанцияны жоготуу мүмкүнчүлүгүн же эч нерсе жоголбосо, аны олуттуу кечигип жеткирүү мүмкүнчүлүгүн караштыруу зарыл. Бардык учурларда, бир эле нерсе жасалат: пакет кайра жөнөтүлөт. Убакытты көзөмөлдөө үчүн бул механизм күтүү интервалынын соңун аныктоого мүмкүндүк берген артка санак таймерин колдонот. Ошентип, пакетте тор TCPKeepAlive демейки боюнча 15 секундага коюлган:

// 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 алдында катар номерлери бар бардык пакеттер ийгиликтүү кабыл алынганын көрсөтүүчү жалпы тастыктоо берилет.
  • күтүү аралыгы бүттү. Пакеттердин жана түшүүлөрдүн жоготууларынын жана кечиктирүүлөрүнүн фактыларын аныктоо үчүн протокол таймерди колдонот. Эгерде күтүү аралыгы бүтсө, жөнөтүүчү тарап бардык жөнөтүлгөн таанылбаган пакеттерди кайра жөнөтөт.

Тандалма кайталоо

Терезенин өлчөмү жана өткөрүү жөндөмдүүлүгүн жайылтуу кечигүү продуктусу чоң болгондо, көп сандагы пакеттер түтүктө болушу мүмкүн. Мындай учурда, бир пакет катасы көп сандагы пакеттердин кайра жөнөтүлүшүнө алып келиши мүмкүн, алардын көбү талап кылынбайт.

мисал

мыкты теориялык практикалык ишке ашырууда топтолгон TCP. Жана эгер кимдир бирөө эң жакшы билсе - Кош келдиңиз.

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

Комментарий кошуу