Misingi ya Uhamisho wa Data Unaoaminika

Misingi ya Uhamisho wa Data Unaoaminika

Kwa wale ambao hutafuta Imejitolea kuelewa mitandao na itifaki.

Kwa kifupi

Makala inazungumzia misingi ya maambukizi ya data ya kuaminika, hutumia mifano kwenye Go, ikijumuisha UDP na TCP. Kulingana na wakati, два, tatu na vitabu "Mitandao ya Kompyuta. Mbinu ya Juu-Chini", vinginevyo kila mtu anajadili Tannenbaum na Oliferov tu.

Itifaki ya safu ya usafiri

Hutoa muunganisho wa kimantiki kati ya michakato ya programu inayoendeshwa kwenye wapangishaji tofauti. Kwa mtazamo wa programu, muunganisho wa kimantiki unaonekana kama chaneli inayounganisha moja kwa moja michakato.

Misingi ya Uhamisho wa Data Unaoaminika

Itifaki za safu ya usafiri inasaidiwa na mifumo ya mwisho, lakini sio na ruta za mtandao (isipokuwa - DPI) Kwa upande wa mtumaji, safu ya usafirishaji hubadilisha data ya safu ya programu inayopokea kutoka kwa mchakato wa kutuma maombi kuwa pakiti za safu za usafirishaji zinazoitwa segments.

Misingi ya Uhamisho wa Data Unaoaminika

Hii inafanywa kwa kugawanyika (ikiwa ni lazima) ujumbe wa safu ya programu katika vipande na kuongeza kichwa cha safu ya usafiri kwa kila mmoja wao.

Misingi ya Uhamisho wa Data Unaoaminika

Safu ya usafiri kisha hupitisha sehemu hiyo kwa safu ya mtandao ya mtumaji, ambapo sehemu hiyo imefungwa kwenye pakiti ya safu ya mtandao (datagram) na kutumwa. Katika mwisho wa kupokea, safu ya mtandao hutoa sehemu ya safu ya usafiri kutoka kwa datagram na kuipitisha hadi safu ya usafiri. Ifuatayo, safu ya usafirishaji huchakata sehemu iliyopokelewa ili data yake ipatikane kwa programu inayopokea.

Misingi ya Uhamisho wa Data Unaoaminika

Kanuni za usambazaji wa data za kuaminika

Usambazaji wa data unaotegemewa kupitia chaneli salama kabisa

Kesi rahisi zaidi. Upande wa kutuma hupokea tu data kutoka kwa safu ya juu, huunda pakiti iliyo nayo, na kuituma kwa kituo.

Seva

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 + надежный канал
    }
}

Mteja

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)
    }
}

Usambazaji wa data unaotegemewa kupitia kituo na hitilafu zinazowezekana

Hatua inayofuata ni kudhani kwamba pakiti zote zinazopitishwa zinapokelewa kwa utaratibu ambao zilitumwa, lakini bits ndani yao zinaweza kuharibiwa kutokana na ukweli kwamba kituo wakati mwingine hupeleka data kwa uharibifu.

Misingi ya Uhamisho wa Data Unaoaminika

Katika kesi hii, taratibu zifuatazo hutumiwa:

  • kugundua makosa;
  • maoni;
  • kusambaza tena.

Itifaki za uhamishaji data zinazotegemewa ambazo zina mbinu sawa za kurudia utumaji mara nyingi huitwa itifaki za Kurudia Kurudia Kiotomatiki (ARQ).
Zaidi ya hayo, inafaa kuzingatia uwezekano wa makosa katika risiti, wakati mpokeaji hatapokea taarifa yoyote kuhusu matokeo ya uhamisho wa pakiti ya mwisho.
Suluhisho la tatizo hili, pia linatumika katika TCP, ni kuongeza sehemu mpya kwenye pakiti ya data iliyo na nambari ya mlolongo wa pakiti.

Misingi ya Uhamisho wa Data Unaoaminika

Usambazaji wa data unaotegemewa kupitia chaneli isiyotegemewa chini ya upotoshaji na upotevu wa pakiti

Pamoja na kupotosha, kwa bahati mbaya, kuna upotezaji wa pakiti kwenye mtandao.
Na ili kutatua tatizo hili, taratibu zinahitajika:

  • kuamua ukweli wa upotezaji wa pakiti;
  • uwasilishaji upya wa pakiti zilizopotea kwa mpokeaji.

Zaidi ya hayo, pamoja na hasara ya mfuko, ni muhimu kutoa kwa uwezekano wa kupoteza risiti au, ikiwa hakuna kitu kinachopotea, utoaji wake kwa kuchelewa kwa kiasi kikubwa. Katika hali zote, kitu kimoja kinafanyika: pakiti inatumwa tena. Ili kudhibiti wakati, utaratibu huu hutumia kipima muda cha kuhesabu, ambacho hukuruhusu kuamua mwisho wa muda wa kusubiri. Kwa hivyo kwenye kifurushi wavu TCPKeepAlive imewekwa kwa sekunde 15 kwa chaguo-msingi:

// defaultTCPKeepAlive is a default constant value for TCPKeepAlive times
// See golang.org/issue/31510
const (
    defaultTCPKeepAlive = 15 * time.Second
)

Upande wa kutuma unahitaji kuanzisha kipima muda kila wakati pakiti inapotumwa (ya kwanza na ya pili), shughulikia kukatizwa na kipima muda na usitishe.

Kwa hivyo, tumezoea dhana kuu za itifaki za uhamishaji data za kuaminika:

  • hundi;
  • nambari za mlolongo wa vifurushi;
  • vipima muda;
  • risiti chanya na hasi.

Lakini si hivyo tu!

Itifaki ya kuaminika ya uhamishaji data na bomba

Katika tofauti ambayo tayari tumezingatia, itifaki ya utoaji wa kuaminika haifai sana. Huanza "kupunguza kasi" upitishaji unaotolewa na njia ya mawasiliano kadri RTT inavyoongezeka. Ili kuongeza ufanisi wake na kutumia vyema uwezo wa njia ya mawasiliano, bomba hutumiwa.

Misingi ya Uhamisho wa Data Unaoaminika

Matumizi ya bomba husababisha:

  • kuongeza idadi ya nambari za mlolongo, kwa kuwa pakiti zote zilizotumwa (isipokuwa kwa retransmissions) lazima zitambuliwe kipekee;
  • hitaji la kuongeza buffers kwenye pande za kupitisha na kupokea.

Safu ya nambari ya mfuatano na mahitaji ya saizi ya bafa hutegemea hatua ambazo itifaki inachukua ili kukabiliana na upotovu, upotevu na ucheleweshaji wa pakiti. Katika kesi ya bomba, kuna njia mbili za kurekebisha makosa:

  • rudisha pakiti za N nyuma;
  • marudio ya kuchagua.

Kurudi nyuma kwa pakiti N - itifaki ya dirisha ya kuteleza

Misingi ya Uhamisho wa Data Unaoaminika

Mtumaji lazima aauni aina tatu za matukio:

  • piga simu kwa itifaki ya kiwango cha juu. Wakati kazi ya kutuma data inaitwa "kutoka juu", upande wa kutuma kwanza huangalia kiwango cha kujaza kwa dirisha (yaani, uwepo wa ujumbe uliotumwa wa N unaosubiri kupokea risiti). Ikiwa dirisha ni tupu, pakiti mpya hutolewa na kupitishwa, na maadili ya kutofautiana yanasasishwa. Vinginevyo, upande wa kutuma unarudisha data kwenye safu ya juu, na hii ni dalili kamili kwamba dirisha limejaa. Kwa kawaida safu ya juu itajaribu kusambaza data tena baada ya muda fulani. Katika programu-tumizi halisi, mtumaji anaweza aidha kuhifadhi data (badala ya kuituma mara moja) au kuwa na utaratibu wa kusawazisha (kama vile semaphore au bendera) ambayo ingeruhusu safu ya juu kuita kazi ya kutuma tu wakati dirisha liko tupu. .
  • kupokea uthibitisho. Katika itifaki, kwa pakiti yenye nambari ya mlolongo N, uthibitisho wa jumla unatolewa unaoonyesha kwamba pakiti zote zilizo na nambari za mlolongo zilizotangulia N zilipokelewa kwa ufanisi.
  • muda wa kusubiri umekwisha. Kuamua ukweli wa hasara na ucheleweshaji wa pakiti na risiti, itifaki hutumia timer. Ikiwa muda wa kuisha utaisha, upande unaotuma hutuma tena pakiti zote ambazo hazijatambuliwa.

marudio ya kuchagua

Wakati saizi ya dirisha na bidhaa ya ucheleweshaji wa uenezi ni kubwa, idadi kubwa ya pakiti inaweza kuwa kwenye bomba. Katika hali hiyo, kosa moja la pakiti inaweza kusababisha idadi kubwa ya pakiti kupitishwa tena, ambazo nyingi hazikuhitajika.

Mfano

Top kinadharia mazoea hukusanywa katika utekelezaji wa vitendo TCP. Na ikiwa mtu anajua jinsi bora - kuwakaribisha.

Seva

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"))
    }
}

Mteja

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)
    }
}

Pato

Taratibu za kuhakikisha uhamishaji na utumiaji wa data unaotegemewa

Mfumo
Maombi, maoni

Angalia jumla
Inatumika kugundua hitilafu kidogo katika pakiti iliyopitishwa

Muda
Huhesabu muda wa kuisha na huonyesha muda wake umeisha. Mwisho unamaanisha kuwa kwa kiwango kikubwa cha uwezekano pakiti au risiti yake inapotea wakati wa maambukizi. Ikiwa pakiti itawasilishwa kwa kuchelewa, lakini haijapotea (kuisha mapema kwa muda wa kuisha), au risiti imepotea, uwasilishaji upya husababisha pakiti ya nakala kwenye upande wa kupokea.

Nambari ya serial
Inatumika kwa kuweka nambari mfuatano za pakiti za data zinazotumwa kutoka kwa mtumaji hadi kwa mpokeaji. Mapungufu katika nambari za mlolongo wa pakiti zilizopokelewa huruhusu mpokeaji kugundua upotezaji wa pakiti. Nambari sawa za mlolongo wa pakiti inamaanisha kuwa pakiti ni nakala za kila mmoja

Uthibitisho
Imetolewa na mwisho wa upokeaji na kuonyesha hadi mwisho wa kutuma kwamba pakiti au kikundi cha pakiti kinacholingana kimepokelewa kwa ufanisi. Kwa kawaida kibali huwa na nambari za mfuatano wa pakiti zilizopokelewa kwa ufanisi. Kulingana na itifaki, uthibitisho wa mtu binafsi na wa kikundi hutofautishwa

Uthibitisho hasi
Inatumiwa na mpokeaji kumjulisha mtumaji kwamba pakiti ilipokelewa vibaya. Kukiri hasi kawaida hujumuisha nambari ya mfuatano wa pakiti ambayo haikupokelewa kwa usahihi

Dirisha, conveyorization
Punguza safu ya nambari za mfuatano ambazo zinaweza kutumika kusambaza pakiti. Multicast na handshake inaweza kwa kiasi kikubwa kuongeza throughput itifaki ikilinganishwa na kusubiri kwa shukrani. Kama tutakavyoona, saizi ya dirisha inaweza kuhesabiwa kulingana na uwezo wa mapokezi na buffering ya mwisho wa kupokea, pamoja na kiwango cha mzigo wa mtandao.

Mifano zaidi ya kutumia Go kwa mitandao

В hazina.

Chanzo: mapenzi.com

Kuongeza maoni