Mga Batayan ng Maaasahang Paglipat ng Data

Mga Batayan ng Maaasahang Paglipat ng Data

Sa mga taong naghahanap Nakatuon sa pag-unawa sa mga network at protocol.

Sa madaling sabi

Tinatalakay ng artikulo ang mga pangunahing kaalaman ng maaasahang paghahatid ng data, nagpapatupad ng mga halimbawa sa Go, kabilang ang UDP at TCP. Batay sa oras, два, tatlo at ang mga aklat na "Computer Networks. Top-Down Approach", kung hindi, ang lahat ay tinatalakay lamang ang Tannenbaum at Oliferov.

Protocol ng layer ng transportasyon

Nagbibigay ng lohikal na koneksyon sa pagitan ng mga proseso ng application na tumatakbo sa iba't ibang mga host. Mula sa pananaw ng application, ang isang lohikal na koneksyon ay mukhang isang channel na direktang nagkokonekta sa mga proseso.

Mga Batayan ng Maaasahang Paglipat ng Data

Mga protocol ng layer ng transportasyon ay sinusuportahan ng mga end system, ngunit hindi ng mga network router (maliban - DPI). Sa panig ng nagpadala, kino-convert ng transport layer ang data ng application layer na natatanggap nito mula sa proseso ng pagpapadala ng aplikasyon sa mga transport layer packet na tinatawag na mga segment.

Mga Batayan ng Maaasahang Paglipat ng Data

Ginagawa ito sa pamamagitan ng paghahati (kung kinakailangan) ang mga mensahe ng layer ng application sa mga fragment at pagdaragdag ng header ng transport layer sa bawat isa sa kanila.

Mga Batayan ng Maaasahang Paglipat ng Data

Pagkatapos ay ipinapasa ng transport layer ang segment sa layer ng network ng nagpadala, kung saan naka-encapsulate ang segment sa isang network layer packet (datagram) at ipinadala. Sa dulo ng pagtanggap, kinukuha ng layer ng network ang segment ng transport layer mula sa datagram at ipinapasa ito sa layer ng transportasyon. Susunod, pinoproseso ng transport layer ang natanggap na segment upang maging available ang data nito sa tumatanggap na application.

Mga Batayan ng Maaasahang Paglipat ng Data

Mga prinsipyo ng maaasahang paghahatid ng data

Maaasahang paghahatid ng data sa isang ganap na secure na channel

Ang pinakasimpleng kaso. Ang panig ng pagpapadala ay tumatanggap lamang ng data mula sa itaas na layer, lumilikha ng isang packet na naglalaman nito, at ipinapadala ito sa channel.

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

Customer

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

Maaasahang paghahatid ng data sa isang channel na may posibleng mga error

Ang susunod na hakbang ay ipagpalagay na ang lahat ng ipinadala na mga packet ay natanggap sa pagkakasunud-sunod kung saan sila ipinadala, ngunit ang mga piraso sa mga ito ay maaaring masira dahil sa ang katunayan na ang channel kung minsan ay nagpapadala ng data na may mga pagbaluktot.

Mga Batayan ng Maaasahang Paglipat ng Data

Sa kasong ito, ginagamit ang mga sumusunod na mekanismo:

  • pagtuklas ng error;
  • puna;
  • muling paghahatid.

Ang mga maaasahang protocol ng paglilipat ng data na may katulad na mga mekanismo para sa paulit-ulit na paghahatid ng maraming beses ay tinatawag na mga protocol ng Automatic Repeat reQuest (ARQ).
Bilang karagdagan, ito ay nagkakahalaga ng pagsasaalang-alang sa posibilidad ng mga pagkakamali sa mga resibo, kapag ang tumatanggap na partido ay hindi makakatanggap ng anumang impormasyon tungkol sa mga resulta ng paglilipat ng huling packet.
Ang solusyon sa problemang ito, na ginagamit din sa TCP, ay magdagdag ng bagong field sa data packet na naglalaman ng sequence number ng packet.

Mga Batayan ng Maaasahang Paglipat ng Data

Maaasahang paghahatid ng data sa isang hindi mapagkakatiwalaang channel na napapailalim sa pagbaluktot at pagkawala ng packet

Kasama ng pagbaluktot, sa kasamaang palad, mayroong pagkawala ng packet sa network.
At upang malutas ang problemang ito, kinakailangan ang mga mekanismo:

  • pagtukoy sa katotohanan ng pagkawala ng packet;
  • muling paghahatid ng mga nawawalang packet sa tumatanggap na partido.

Bukod pa rito, bilang karagdagan sa pagkawala ng pakete, kinakailangang magbigay ng posibilidad ng pagkawala ng resibo o, kung walang nawala, ang paghahatid nito nang may malaking pagkaantala. Sa lahat ng kaso, ang parehong bagay ay ginagawa: ang packet ay muling ipinadala. Upang kontrolin ang oras, ang mekanismong ito ay gumagamit ng countdown timer, na nagbibigay-daan sa iyo upang matukoy ang katapusan ng agwat ng paghihintay. Kaya sa pakete neto Ang TCPKeepAlive ay nakatakda sa 15 segundo bilang default:

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

Ang panig ng pagpapadala ay kailangang magsimula ng isang timer sa tuwing ang isang packet ay ipinadala (kapwa sa una at pangalawang pagkakataon), hawakan ang mga pagkaantala mula sa timer at itigil ito.

Kaya, naging pamilyar kami sa mga pangunahing konsepto ng maaasahang mga protocol ng paglilipat ng data:

  • mga checksum;
  • mga numero ng pagkakasunud-sunod ng mga pakete;
  • mga timer;
  • positibo at negatibong mga resibo.

Ngunit hindi lang iyon!

Maaasahang data transfer protocol na may pipelining

Sa variant na napag-isipan na namin, ang maaasahang protocol ng paghahatid ay napaka-inefficient. Nagsisimula itong "pabagalin" ang paghahatid na ibinigay ng channel ng komunikasyon habang tumataas ang RTT. Upang mapataas ang kahusayan nito at mas mahusay na magamit ang kapasidad ng channel ng komunikasyon, ginagamit ang pipelining.

Mga Batayan ng Maaasahang Paglipat ng Data

Ang paggamit ng pipelining ay humahantong sa:

  • pagtaas ng hanay ng mga numero ng pagkakasunud-sunod, dahil ang lahat ng ipinadalang packet (maliban sa mga muling pagpapadala) ay dapat na natatanging matukoy;
  • ang pangangailangan na dagdagan ang mga buffer sa mga panig ng pagpapadala at pagtanggap.

Ang hanay ng numero ng sequence at mga kinakailangan sa laki ng buffer ay nakasalalay sa mga pagkilos na ginagawa ng protocol bilang tugon sa pagkasira, pagkawala, at pagkaantala ng packet. Sa kaso ng pipelining, mayroong dalawang paraan para sa pagwawasto ng mga error:

  • ibalik ang N packet;
  • piling pag-uulit.

Pagbabalik N packet - sliding window protocol

Mga Batayan ng Maaasahang Paglipat ng Data

Dapat suportahan ng nagpadala ang tatlong uri ng mga kaganapan:

  • tawag sa pamamagitan ng mas mataas na antas ng protocol. Kapag ang function ng pagpapadala ng data ay tinatawag na "mula sa itaas", sinusuri muna ng panig ng pagpapadala ang antas ng pagpuno ng window (iyon ay, ang pagkakaroon ng N ipinadalang mga mensahe na naghihintay ng pagtanggap ng mga resibo). Kung ang window ay walang laman, ang isang bagong packet ay nabuo at ipinadala, at ang mga variable na halaga ay ina-update. Kung hindi man, ang panig ng pagpapadala ay nagbabalik ng data sa itaas na layer, at ito ay isang implicit na indikasyon na ang window ay puno na. Karaniwang susubukan ng itaas na layer na ipadala muli ang data pagkalipas ng ilang oras. Sa isang tunay na aplikasyon, malamang na i-buffer ng nagpadala ang data (sa halip na ipadala ito kaagad) o magkaroon ng mekanismo ng pag-synchronize (tulad ng semaphore o flag) na magbibigay-daan sa itaas na layer na tawagan ang function ng pagpapadala kapag walang laman ang window. .
  • pagtanggap ng kumpirmasyon. Sa protocol, para sa isang packet na may sequence number N, ang isang pangkalahatang pagkilala ay inilabas na nagpapahiwatig na ang lahat ng mga packet na may mga sequence number na nauuna sa N ay matagumpay na natanggap.
  • ang agwat ng paghihintay ay nag-expire na. Upang matukoy ang mga katotohanan ng mga pagkalugi at pagkaantala ng mga packet at resibo, ang protocol ay gumagamit ng timer. Kung ang agwat ng timeout ay mag-e-expire, ang panig ng pagpapadala ay muling magpapadala ng lahat ng ipinadalang hindi kilalang packet.

Pinipiling pag-uulit

Kapag ang laki ng window at ang throughput-propagation delay na produkto ay malaki, ang isang malaking bilang ng mga packet ay maaaring nasa pipeline. Sa ganoong kaso, ang isang solong packet error ay maaaring maging sanhi ng malaking bilang ng mga packet na muling maipadala, karamihan sa mga ito ay hindi kinakailangan.

Halimbawa

Tuktok teoretikal ang mga kasanayan ay kinokolekta sa praktikal na pagpapatupad TCP. At kung may nakakaalam kung paano pinakamahusay - maligayang pagdating.

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

Customer

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

Pagbubuhos

Mga mekanismo upang matiyak ang maaasahang paglilipat at paggamit ng data

Механизм
Application, komento

Suriin ang kabuuan
Ginagamit upang makita ang mga bit error sa isang ipinadalang packet

Timer
Binibilang ang agwat ng timeout at ipinapahiwatig kung kailan ito nag-expire. Ang huli ay nangangahulugan na may mataas na antas ng posibilidad na mawala ang packet o ang resibo nito sa panahon ng paghahatid. Kung ang isang packet ay naihatid nang may pagkaantala, ngunit hindi nawala (napaaga na pag-expire ng timeout interval), o ang isang resibo ay nawala, ang muling pagpapadala ay hahantong sa isang duplicate na packet sa gilid ng pagtanggap.

Serial number
Ginagamit para sa sequential numbering ng mga data packet na ipinadala mula sa nagpadala hanggang sa tatanggap. Ang mga gaps sa sequence number ng mga natanggap na packet ay nagbibigay-daan sa receiver na makakita ng packet loss. Ang parehong mga numero ng sequence ng packet ay nangangahulugan na ang mga packet ay mga duplicate ng bawat isa

Kumpil
Binuo ng tatanggap na dulo at nagpapahiwatig sa pagpapadala ng dulo na ang kaukulang packet o grupo ng mga packet ay matagumpay na natanggap. Karaniwan ang pagkilala ay naglalaman ng mga sequence number ng matagumpay na natanggap na mga packet. Depende sa protocol, ang mga kumpirmasyon ng indibidwal at grupo ay nakikilala

Negatibong kumpirmasyon
Ginamit ng tatanggap upang ipaalam sa nagpadala na ang packet ay natanggap nang hindi tama. Karaniwang kasama sa negatibong pagkilala ang sequence number ng packet na hindi wastong natanggap

Window, conveyorization
Limitahan ang hanay ng mga sequence number na maaaring magamit upang magpadala ng mga packet. Ang multicast at handshake ay maaaring makabuluhang tumaas ang protocol throughput kumpara sa paghihintay ng mga pagkilala. Tulad ng makikita natin, ang laki ng window ay maaaring kalkulahin batay sa pagtanggap at mga kakayahan sa pag-buffer ng dulo ng pagtanggap, pati na rin ang antas ng pagkarga ng network

Higit pang mga halimbawa ng paggamit ng Go para sa networking

В mga repositoryo.

Pinagmulan: www.habr.com

Magdagdag ng komento