sieci_komputerowe:realizacja_niezawodnosci_w_tcp [mgr Wiki]

[[sieci_komputerowe:realizacja_niezawodnosci_w_tcp]]
mgr Wiki

Pytanie: “Omów sposób realizacji warunku niezawodności przez protokół TCP”

:wersja pdf

# Niezawodność TCP

W modelu OSI protokół TCP1) jest protokołem 4. warstwy, czyli warstwy transportowej. W modelu tym znajduje się ponad protokołem IP, który jest protokołem 3. warstwy, czyli warstwy sieciowej. Protokół IP jest protokołem zawodnym. Jest opisywany jako best effort delivery protocol, tzn. postara się dostarczyć dane, ale nie daje żadnej gwarancji, że to się powiedzie. Problemy jakie mogą wystąpić, to: przekłamanie danych, zła kolejność pakietów, zduplikowane pakiety i/lub zagubione pakiety. Jednym z celów dla których powstał protokół TCP to właśnie zapobieganie tym problemom. Wykorzystuje do tego mechanizm sumy kontrolnej oraz pozytywnych potwierdzeń z retransmisją (ang. positive acknowledgment with retransmission).

## Przekłamanie danych

Jednym z nagłówków segmentu TCP jest 16-bitowe pole sumy kontrolnej (ang. checksum). Do wyliczenia sumy kontrolnej brany jest cały segment TCP (z polem sumy kontrolnej ustawionym na zero) plus dodatkowo z nagłówków IP: adres źródłowy, adres docelowy, protokół wyższej warstwy, rozmiar danych protokołu wyższej warstwy. Powyższe dane dzielone są na 16-bitowe słowa, a jeśli występuje nieparzysta ilość oktetów, to do ostatniego dołączany jest oktet składający się z samych zer. Następnie słowa są dodawane w kodzie uzupełnieniowym do jedynki. Wynik przedstawiony w kodzie uzupełnieniowym do jedynki wstawiany jest do pola sumy kontrolnej.

Docelowa maszyna po odebraniu danych wykonuje tą samą operację z tym, że teraz pole sumy kontrolnej ma już ustawioną wartość. Jeśli wartość obliczonej sumy będzie wynosiła `0xFFFF` (lub w kodzie uzupełnieniowym do jedynki `0×0000`), to znaczy że dane nie zostały uszkodzone.

Na końcu jest załączony kod źródłowy programu, który oblicza sumę kontrolną dla tablicy danych typu `unsigned short`. Nas najbardziej interesuje funkcja `checksum();`

## Zła kolejność pakietów

Jednym z nagłówków segmentu TCP jest 32-bitowe pole numeru sekwencyjnego. Każdy segment przed wysłaniem ma nadany numer. Numery początkowe segmentów są ustalane na etapie nawiązania połączenia TCP (mechanizm three-way handshake). Jeśli zdarzy się, że segmenty dotrą do maszyny docelowej w złej kolejności, to na podstawie numerów sekwencyjnych można ustalić ich właściwą kolejność.

Każdy bajt danych w segmencie TCP zwiększa licznik o 1. Również segmenty TCP z ustawioną flagą `SYN` lub `FIN` zwiększają wartość licznika, gdyż uczestniczą one w otwieraniu i zamykaniu połączenia i muszą być przesyłane w niezawodny sposób.

## Zagubione pakiety

Numery sekwencyjne segmentów są wykorzystywane nie tylko do ustalania ich prawidłowej kolejności ale również do potwierdzania ich odbioru. Jednym z nagłówków segmentu TCP jest 32-bitowe pole numeru potwierdzenia. Rozważmy przykład wysłania segmentu o numerze S i rozmiarze R z maszyny źródłowej Z do maszyny docelowej D. Stos TCP/IP maszyny Z przechowuje ten segment w buforze i jednocześnie uruchamia licznik. Stos TCP/IP maszyny D odbiera segment i odsyła segment potwierdzenia z ustawioną flagą ACK i numerem potwierdzenia równym S+R. Numer potwierdzenia równy S+R, to numer sekwencyjny kolejnego segmentu, jaki oczekuje maszyna D od maszyny Z. Stos TCP/IP maszyny Z po otrzymaniu potwierdzenia usuwa segment z bufora. Gdyby potwierdzenie nie przyszło przed upłynięciem czasu oczekiwania, to segment z bufora byłby wysłany jeszcze raz. Dzięki temu prostemu mechanizmowi mamy pewność, że każdy segment dotrze do celu.

## Zduplikowane pakiety

Konsekwencją powyższego rozwiązania jest to, że mogą pojawić się zduplikowane segmenty. Jeśli z powodu problemów w sieci potwierdzenie odbioru nie dotrze do maszyny źródłowej w ogóle lub przed upłynięciem czasu oczekiwania, to maszyna źródłowa wyśle niepotwierdzony segment jeszcze raz. Jednak rozwiązanie tego problemu jest bardzo proste. Zduplikowany segment będzie miał ten sam numer sekwencyjny co pierwotny, więc stos TCP/IP w maszynie docelowej z łatwością go wykryje i po prostu zignoruje.

## Dodatkowe informacje

- http://www.netfor2.com/checksum.html – mechanizm wyznaczania sumy kontrolnej
- http://en.wikipedia.org/wiki/Signed_number_representations – kod uzupełnieniowy do jedynki
- http://www.ietf.org/rfc/rfc0793.txt – rozdział 3.3 - numery sekwencyjne
- http://www.staff.amu.edu.pl/~psi/informatyka/tcpip/tcp.htm – informacje o niezawodności

## Obliczanie sumy kontrolnej

    #include <iostream>
    #include <sstream>
    using namespace std;

    unsigned short checksum(unsigned short data[], int size);

    template<class T>
    void printBinary(T value);

    int main()
    {
        unsigned short data[5] = { 0x0100, 0xF203, 0xF4F5, 0xF6F7, 0x0000};

        unsigned short sum = checksum(data, 10);

        data[4] = sum;
        unsigned short sum2 = checksum(data, 10);

        printBinary<unsigned short>(sum);
        cout << " - " << hex << showbase << sum << endl;

        printBinary<unsigned short>(sum2);
        cout << " - " << hex << showbase << sum2 << endl;
    }

    unsigned short checksum(unsigned short data[], int size)
    {
        unsigned short sum = 0;
        for (int i = 0; i < size; i++)
        {
            unsigned int t2 = sum + data[i];   // full sum
            t2 = t2 >> 16;
            unsigned short adder = (unsigned short) t2;   // carry

            sum += data[i];   // add without carry
            sum += adder;   // add carry
        }

        return ~sum;
    }

    template<class T>
    void printBinary(const T value)
    {
        int typeSize = sizeof(T) * 8;
        T mask;
        ostringstream strstream;

        for (int i = 0; i < typeSize; i++)
        {
            mask = 1 << (typeSize-1 - i);
            if (value & mask)
            {
                strstream << "1";
            }
            else
            {
                strstream << "0";
            }

            if ( (i+1) % 8 == 0)
            {
                strstream << " ";
            }
        }

        cout << strstream.str();
    }

1) Transmission Control Protocol
sieci_komputerowe/realizacja_niezawodnosci_w_tcp.txt · Last modified: 2006/05/24 16:28 by 213.134.174.237