Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Диаграмма состояний TCP соединения.




Временная диаграмма установления TCP соединения.

Временная диаграмма завершения TCP соединения.

Временная диаграмма обмена данными.

Описание алгоритма подсчёта контрольной суммы TCP сегмента.

В общих чертах алгоритм расчета контрольной суммы очень прост:

1. Соседние октеты информации, для которой создается контрольная сумма, объединяются в 16-битовые целые числа и для этих чисел формируется 16-битовое поразрядное дополнение до 1.

2. При расчете контрольной суммы значение самого поля контрольной суммы принимается нулевым. Для 16-битовых поразрядных дополнений вычисляется сумма. Для полученного в результате 16-битового целого числа создается 16-битовое поразрядное дополнение до 1 и помещается в поле контрольной суммы.

3. Для проверки контрольной суммы вычисляется сумма поразрядных дополнений до 1 для того же набора октетов, включая поле контрольной суммы. Если в результате получается значение, все биты которого равны 1 (-0 в арифметике дополнений до 1), это говорит о корректности контрольной суммы.

Временная диаграмма одновременного завершения TCP соединения.

 

 

Исходный код и результаты работы программы.

Main.cpp

#include "buffer.h"

#include "TcpSegment.h"

#include <conio.h>

 

void const GetTcpHeader(TcpSegment &head);

void GetTcpData(TcpSegment &head);

void SetTcpHeader(TcpSegment &head);

void ContBits(byte contbits);

void Reserved(uint16_t reserved);

void Comparison(TcpSegment &head);

 

void main()

{

cout << "Hex Data Vector:\n";

shared_ptr <vector<byte>> v(new vector < byte >({

/*0x45, 0x00, 0x01, 0x43, 0x00, 0x14, 0x40, 0x00, 0x80, 0x06,

0x8f, 0xdf, 0x0a, 0x00, 0x02, 0x69, 0xd5, 0xdb, 0x87, 0x7d,*/

0xc0, 0x06, 0x0f, 0x42, 0x43, 0x51, 0xbb, 0x09, 0x00, 0x00,

0xfa, 0x02, 0x50, 0x18, 0xfa, 0xf0, 0x32, 0x2b, 0x00, 0x00 }));

for (unsigned int i = 0; i < v->size(); i++)

cout << hex << "0x" << (int)*(v->data() + i) << " ";

buffer buf(v);

try

{

buffer buf(v);

}

catch (exception &e)

{

cout << "NULLPTR";

}

TcpSegment TcpHead(buf);

int ans = 0;

do {

cout << "\n\nWhat do you want to do?: \n";

cout << "1. Get Header;\n2. Set Header;\n3. Get Data;\n4. Wireshark vs. C++;\n0. Quit Programm.\n\n";

cout << "Your choice: ";

cin >> ans;

switch (ans)

{

case 1: GetTcpHeader(TcpHead); break;

case 2: SetTcpHeader(TcpHead); break;

case 3: GetTcpData(TcpHead); break;

case 4: Comparison(TcpHead); break;

case 0: break;

}

} while (ans!= 0);

}

void Reserved(uint16_t reserved)

{

char name1[][10] = { "Not Set", "Set" };

char name2[][10] = { "Not Set", "Set" };

char name3[][10] = { "Not Set", "Set" };

char name4[][10] = { "Not Set", "Set" };

int bits = ((reserved >> 9) & 111); //0000111111000000 => 0000000000000111

cout << "Reserved: " << name1[bits] << endl;

bits = ((reserved >> 8) & 1); //0000111111000000 => 0000000000001111

cout << "Nonce: " << name2[bits] << endl;

bits = ((reserved >> 7) & 1);

cout << "CWR: " << name3[bits] << endl;

bits = ((reserved >> 6) & 1);

cout << "ECN-Echo: " << name4[bits] << endl;

}

void ContBits(byte contbits)

{

char name1[][10] = { "Not Set", "Set" };

char name2[][10] = { "Not Set", "Set" };

char name3[][10] = { "Not Set", "Set" };

char name4[][10] = { "Not Set", "Set" };

char name5[][10] = { "Not Set", "Set" };

char name6[][10] = { "Not Set", "Set" };

int bits = ((contbits >> 5) & 1); //00111111 => 00000001

cout << "URG: " << name1[bits] << endl;

bits = ((contbits >> 4) & 1); //00111111 => 00000011

cout << "ACK: " << name2[bits] << endl;

bits = ((contbits >> 3) & 1);

cout << "PSH: " << name3[bits] << endl;

bits = ((contbits >> 2) & 1);

cout << "RST: " << name4[bits] << endl;

bits = ((contbits >> 1) & 1);

cout << "SYN: " << name5[bits] << endl;

bits = (contbits & 1);

cout << "FIN: " << name6[bits] << endl;

}

void const GetTcpHeader(TcpSegment &head)

{

int ans = 0;

start:

cout << "\nWhat header field do you want to see?: \n";

cout << "1. Source port;\n2. Destination port;\n3. Sequence number;\n4. Acknowledgement number;\n5. Data offset;\n6. Reserved;\n7. Control bits;\n";

cout << "8. Window;\n9. Checksum;\n10. Urgent pointer;\n0. Return to menu\n ";

do {

cout << "\nYour choice: ";

cin >> ans;

switch (ans) {

case 1: cout << "Source port: " << endl << dec << (int)head.GetSourcePort() << endl;; break;

case 2: cout << "Destination port: " << endl << dec << (int)head.GetDestinationPort() << endl;; break;

case 3: cout << "Sequence number: " << endl << hex << (int)head.GetSequenceNumber() << endl; break;

case 4: cout << "Acknowledgement number: " << endl << hex << (int)head.GetAckNumber() << endl; break;

case 5: cout << "Data Offset: " << endl << dec << (int)head.GetOffset() << " bytes" << endl; break;

case 6: cout << "Reserved: \n"; Reserved(head.GetReserved()); break;

case 7: cout << "Control Bits: \n"; ContBits(head.GetContBits()); break;

case 8: cout << "Window: " << endl << dec << (int)head.GetWindow() << endl; break;

case 9: cout << "Checksum: " << endl << hex << "0x" << (int)head.GetChecksum() << endl; break;

case 10: cout << "Urgent pointer: " << endl << dec << (int)head.GetUrgPointer() << endl; break;

default: cout << "ERROR\n"; goto start;

case 0: break;

}

} while (ans!= 0);

}

void SetTcpHeader(TcpSegment &head)

{

int ans = 0;

start:

cout << "\nWhat header field do you want to set?: \n";

cout << "1. Source port;\n2. Destination port;\n3. Sequence number;\n4. Acknowledgement number;\n5. Data offset;\n6. Reserved;\n7. Control bits;\n";

cout << "8. Window;\n9. Checksum;\n10. Urgent pointer;\n0. Return to menu\n ";

do {

cout << "\nYour choice: ";

cin >> ans;

switch (ans) {

case 1:

{

int i = 0;

cout << endl << "Source port - header's bytes 1 & 2: enter the number [1..65 535]: ";

do {

cin >> i;

if (i <= 0 || i > 65535)

cout << "\nERROR: Enter the number [1..65 535]: ";

} while (i <= 0 || i > 15);

head.SetSourcePort(i);

break;

}

case 2:

{

int i = 0;

cout << endl << "Destination porth - header's bytes 3 & 4: enter the number [1..65 535]: ";

do {

cin >> i;

if (i < 0 || i > 65535)

cout << "\nERROR: Enter the number [1..65 535]: ";

} while (i < 0 || i > 15);

head.SetDestinationPort(i);

break;

}

case 3:

{

uint16_t i = 0;

cout << endl << "Sequence number - header's bytes 5, 6, 7, 8: enter the number [0..65 535]: ";

do {

cin >> i;

if (i < 0 || i > 65535)

cout << "\nERROR: Enter the number [0..65 535]: ";

} while (i < 0 || i > 255);

head.SetSequenceNumber(i);

break;

}

case 4:

{

uint16_t i = 0;

cout << endl << "Acknowledgement number - header's bytes 9, 10, 11, 12: enter the number [0..65 535]: ";

do {

cin >> i;

if (i < 20 || i > 65535)

cout << "\nERROR: Enter the number [0..65 535]: ";

} while (i < 20 || i > 65535);

head.SetAckNumber(i);

break;

}

case 5:

{

uint16_t i = 0;

cout << endl << "Header's offset - 4 bits: enter the number [1..15]: ";

do {

cin >> i;

if (i <= 0 || i > 15)

cout << "\nERROR: Enter the number [1..15]: ";

} while (i <= 0 || i > 15);

head.SetOffset(i);

break;

}

case 6:

{

int i = 0;

head.SetReserved(i);

break;

}

case 7:

{

uint16_t i = 0;

cout << endl << "Control bits - 6 bits: enter the number [15..63]: "; //63 = 00111111

do {

cin >> i;

if (i < 15 || i > 63)

cout << "\nERROR: Enter the number [15..63]: ";

} while (i < 15 || i > 63);

head.SetContBits(i);

break;

}

case 8:

{

int i = 0;

cout << endl << "Window size value - header's bytes 15 & 16: enter the number [0..65 535]: ";

do {

cin >> i;

if (i < 0 || i > 65535)

cout << "\nERROR: Enter the number [0..65 535]: ";

} while (i < 0 || i > 65535);

head.SetWindow(i);

break;

}

case 9:

{

int i = 0;

cout << endl << "Checksum - header's bytes 17 & 18: enter the number [0..65 535]: ";

do {

cin >> i;

if (i < 0 || i > 65535)

cout << "\nERROR: Enter the number [0..65 535]: ";

} while (i < 0 || i > 65535);

head.SetChecksum(i);

break;

}

case 10:

{

uint16_t i = 0;

cout << endl << "Urgent pointer - header's bytes 19 & 20: enter the number [0..65 535]: ";

do {

cin >> i;

if (i < 0 || i > 65535)

cout << "\nERROR: Enter the number [0..65 535]: ";

} while (i < 0 || i > 65535);

head.SetUrgPointer(i);

break;

}

default: cout << endl << "ERROR\n"; goto start;

case 0: break;

}

} while (ans!= 0);

}

void GetTcpData(TcpSegment &head)

{

cout << "\nTCP Segment's Data:\n";

buffer data = buffer(head.GetData(head), 20, head.GetData(head).GetLength());

for (int i = 0; i < head.GetData(head).GetLength(); i++)

cout << hex << (int)data[i];

cout << "\n\n";

 

}

void Comparison(TcpSegment &head)

{

cout << "\t\t\t\tWireshark \tvs. \tC++";

cout << "\nSource port: \t\t\t49158" << dec << "\t\t\t" << (int)head.GetSourcePort() << endl;;

cout << "Destination port: \t\t3906" << dec << "\t\t\t" << (int)head.GetDestinationPort() << endl;;

cout << "Sequence number: \t\t1129429769" << dec << "\t\t" << (int)head.GetSequenceNumber() << endl;;

cout << "Acknowledgement number: \t64002" << dec << "\t\t\t" << (int)head.GetAckNumber() << endl;

cout << "Data offset: \t\t\t20 bytes" << dec << "\t\t\t" << (int)head.GetOffset() << " bytes" << endl;

cout << "Reserved: \t\t\t0" << dec << "\t\t\t" << (int)head.GetReserved() << endl;;

cout << "Control bits: \t\t\t18" << hex << "\t\t\t" << (int)head.GetContBits() << endl;

cout << "Window: \t\t\t64240" << dec << "\t\t\t" << (int)head.GetWindow() << endl;

cout << "Checksum: \t\t\t332b" << hex << "\t\t\t" << (int)head.GetChecksum() << endl;

cout << "Urgent pointer: \t\t0" << dec << "\t\t\t" << (int)head.GetUrgPointer() << endl;

}

Buffer.h

#include <memory>

#include <iostream>

#include <vector>

#include <conio.h>

#include <stdlib.h>

#include <exception>

using namespace std;

 

typedef uint8_t byte;

 

/*Класс "Буфер", содержит индекс начала буфера внутри вектора,

длину буфера, умный указатель на вектор.*/

 

class buffer {

uint32_t m_start;

uint32_t m_length;

shared_ptr <vector<byte>> m_data;

public:

buffer();

buffer(shared_ptr <vector<byte>> data);

buffer(shared_ptr <vector<byte>> data, uint32_t start, uint32_t length);

buffer(buffer b, uint32_t start, uint32_t length);

byte& operator[](uint32_t index);

int const GetLength();

buffer operator=(buffer& b);

};

Buffer.cpp

#include "buffer.h";

#include <exception>

using namespace std;

 

buffer::buffer()

{

m_start = 0;

m_length = 0;

m_data = 0;

}

buffer::buffer(shared_ptr <vector<byte>> data)

{

if (data == nullptr) throw exception("Error");

m_data = data;

m_start = 0;

m_length = data->size();

}

buffer::buffer(shared_ptr <vector<byte>> data, uint32_t start, uint32_t length)

{

m_data = data;

m_start = start;

m_length = length;

}

buffer::buffer(buffer b, uint32_t start, uint32_t length)

{

m_data = b.m_data;

m_start = start;

m_length = length;

}

byte& buffer::operator[](uint32_t index) { return *(m_data->data() + index + m_start); }

int const buffer::GetLength() { return m_length; }

buffer buffer::operator=(buffer& b)

{

m_data = b.m_data;

m_start = b.m_start;

m_length = b.m_length;

return *this;

}

TCPSegment.h

#include <memory>

#include <iostream>

#include <vector>

#include <conio.h>

#include <stdlib.h>

using namespace std;

 

typedef uint8_t byte;

 

/*Класс дэйтаграммы, элементы - 3 разных буфера,

указывающие на один вектор, но на разные его части.*/

 

class TcpSegment {

buffer data;

buffer header;

buffer option;

public:

TcpSegment(buffer a);

uint16_t const GetSourcePort();

uint16_t const GetDestinationPort();

uint32_t const GetSequenceNumber();

uint32_t const GetAckNumber();

byte const GetOffset();

uint16_t const GetReserved();

byte const GetContBits();

uint16_t const GetWindow();

uint16_t const GetChecksum();

uint16_t const GetUrgPointer();

void SetSourcePort(int i);

void SetDestinationPort(int i);

void SetSequenceNumber(uint16_t i);

void SetAckNumber(uint16_t i);

void SetOffset(uint16_t i);

void SetReserved(int i);

void SetContBits(uint16_t i);

void SetWindow(int i);

void SetChecksum(int i);

void SetUrgPointer(uint16_t i);

buffer TcpSegment::GetData(TcpSegment &head);

};

 

TCPSegment.cpp

#include "buffer.h"

#include "TcpSegment.h"

 

TcpSegment::TcpSegment(buffer a)

{

auto len = a[0] & 0x0F;

len *= 4;

auto optionLen = len - 20;

auto totalLen = (a[2] * 0x100) + a[3];

header = buffer(a, 0, 20);

option = buffer(a, 20, optionLen);

data = buffer(a, len, totalLen - len);

}

uint16_t const TcpSegment::GetSourcePort() { return (header[0] * 0x100) + header[1]; }

uint16_t const TcpSegment::GetDestinationPort() { return (header[2] * 0x100) + header[3]; }

uint32_t const TcpSegment::GetSequenceNumber() { return (((header[4] * 0x100) + header[5]) * 0x100 + header[6]) * 0x100 + header[7]; }

uint32_t const TcpSegment::GetAckNumber() { return (((header[8] * 0x100) + header[9]) * 0x100 + header[10]) * 0x100 + header[11]; }

byte const TcpSegment::GetOffset() { return (header[12] >> 4) * 4; } //размер в 4-х байтных словах

uint16_t const TcpSegment::GetReserved() { uint16_t temp = (header[12] * 0x100) + header[13]; return (temp & 0xfc0); } //fc0 = 0000111111000000

byte const TcpSegment::GetContBits() { return (header[13] & 0x3f); } //3f = 00111111 (берем 6 последних битов)

uint16_t const TcpSegment::GetWindow() { return (header[14] * 0x100) + header[15]; }

uint16_t const TcpSegment::GetChecksum() { return (header[16] * 0x100) + header[17]; }

uint16_t const TcpSegment::GetUrgPointer() { return (header[18]) + header[19]; }

void TcpSegment::SetSourcePort(int i)

{

header[0] = header[0] & 0;

header[0] = header[0] | (i >> 8);

header[1] = header[1] & 0;

header[1] = header[1] | (i & 255);

}

void TcpSegment::SetDestinationPort(int i)

{

header[2] = header[2] & 0;

header[2] = header[2] | (i >> 8);

header[3] = header[3] & 0;

header[3] = header[3] | (i & 255);

}

void TcpSegment::SetSequenceNumber(uint16_t i)

{

header[1] = i;

}

void TcpSegment::SetAckNumber(uint16_t i)

{

header[2] = header[2] & 0;

header[2] = header[2] | (i >> 8);

header[3] = header[3] & 0;

header[3] = header[3] | (i & 255);

}

void TcpSegment::SetOffset(uint16_t i)

{

header[12] = header[12] & 15;

header[12] = header[12] | (i << 4);

}

void TcpSegment::SetReserved(int i)

{

cout << "No need in setting Reserved field";

}

void TcpSegment::SetContBits(uint16_t i)

{

header[13] = header[13] & (63 << 2);

header[13] = header[13] | i;

}

void TcpSegment::SetWindow(int i)

{

header[14] = header[14] & 0;

header[14] = header[14] | (i >> 8);

header[15] = header[15] & 0;

header[15] = header[15] | (i & 255);

}

void TcpSegment::SetChecksum(int i)

{

header[16] = header[16] & 0;

header[16] = header[16] | (i >> 8);

header[17] = header[17] & 0;

header[17] = header[17] | (i & 255);

}

void TcpSegment::SetUrgPointer(uint16_t i)

{

header[18] = header[18] & 0;

header[18] = header[18] | (i >> 8);

header[19] = header[19] & 0;

header[19] = header[19] | (i & 255);

}

buffer TcpSegment::GetData(TcpSegment &head) { return data; }

Выводы.

Изучил принцип работы протокола TCP, структуру TCP-сегмента.

Контрольные вопросы

Назначение протокола TCP.

Механизм TCP предоставляет поток данных с предварительной установкой соединения, осуществляет повторный запрос данных в случае потери данных и устраняет дублирование при получении двух копий одного пакета, гарантируя тем самым, в отличие от UDP, целостность передаваемых данных и уведомление отправителя о результатах передачи.

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...