Диаграмма состояний TCP соединения.
⇐ ПредыдущаяСтр 2 из 2 Временная диаграмма установления 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 Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|