Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <fstream>
- #include <iostream>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <WinSock2.h>
- #include <thread>
- #include <ctime>
- #include "Packet.h"
- #define POLY 0x8408
- #define MSSG_LEN 20000
- #pragma comment(lib,"ws2_32.lib")
- typedef struct sockaddr_in SADDRIN;
- typedef struct sockaddr SADDR;
- typedef struct message {
- unsigned short crc;
- short flag;
- int length;
- int numOfFrags;
- int kolkaty;
- }MESS;
- bool LOCK = TRUE;
- /*
- FLAGS:
- 1 - SYN
- 2 - SYNACK
- 3 - ACK
- 5 - TXT sprava
- 6 - Keep alive signal
- 7 - Paket prisiel poskodeny
- 10 - FIN
- 11 - FINACK
- 20 - prve upozornenie o subore, v datach je jeho meno
- 21 - data suboru
- 22 - koniec suboru
- 100 - Umyselne vlozena chyba
- */
- //using namespace std;
- void client_startup(int port, char* server_ip, int FRAGMAX);
- void server_startup(int port);
- unsigned short getCRC(char *data_p, unsigned short length);
- void vypisPaket(MESS *received, char *start_data);
- void clear_field(char *field, int len);
- bool check_packet(MESS *packet);
- void concurent_alive(SOCKET st, SADDRIN client, int size_mssg);
- int main() {
- char serv_ip[20];
- std::cout << "Dobry den, zvolte cislo pre vybranie strany spojenia:" << std::endl << "\t1: klient - odosiela data" << std::endl << "\t2: server - prijima data" << std::endl;
- int option, fragmax = 10, port = 27500;
- std::cin >> option;
- switch (option) {
- case 1:
- std::cout << "Zadaj ip, na ktoru chces posielat spravy" << std::endl;
- std::cin >> serv_ip;
- std::cin.ignore();
- if (serv_ip[0] == 'l')
- strcpy(serv_ip, "127.0.0.1");
- std::cout << "Zadaj maximalnu velkost fragmentu" << std::endl;
- std::cin >> fragmax;
- std::cin.ignore();
- std::cout << "Teraz zadaj cislo portu" << std::endl;
- std::cin >> port;
- std::cin.ignore();
- client_startup(port, serv_ip, fragmax);
- break;
- case 2:
- std::cout << "Teraz zadaj cislo portu" << std::endl;
- std::cin >> port;
- std::cin.ignore();
- server_startup(port);
- break;
- default:
- std::cout << "Zle cislo!" << std::endl;
- break;
- }
- return 0;
- }
- void concurent_alive(SOCKET st, SADDRIN client, int size_mssg) {
- //najskor 100 krat zmeria cas, potom ho spriemeruje a nasledne posiela podla toho keep alive signaly a flagom 6
- int recv_mssg_len, from_mssg_len = sizeof(client);
- char *signal = (char*)malloc(sizeof(MESS) * sizeof(char));
- clear_field(signal, sizeof(MESS));
- MESS *head = (MESS*)signal;
- head->flag = 6;
- head->crc = getCRC((char*)head + sizeof(short), sizeof(MESS) + head->length - sizeof(short));
- //zmeriam si ako dlho trva pokial pride paket na server(tam sa spracuje) a spat - "round trip time"
- clock_t start = clock();
- if (sendto(st, signal, sizeof(MESS), 0, (SADDR*)&client, size_mssg) == SOCKET_ERROR) {
- std::cout << "Odosielanie zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- if ((recv_mssg_len = recvfrom(st, signal, sizeof(MESS), 0, (SADDR*)&client, &from_mssg_len)) == SOCKET_ERROR) {
- std::cout << "Prijem SYNACK zlyhal, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- clock_t finish = clock();
- int roundTT = 1000 * (double(finish - start) / CLOCKS_PER_SEC);
- //podla zisteneho round trip timu teraz posielam keep alive signaly
- while (LOCK) {
- head->flag = 6;
- head->crc = getCRC((char*)head + sizeof(short), sizeof(MESS) + head->length - sizeof(short));
- if (sendto(st, signal, sizeof(MESS), 0, (SADDR*)&client, size_mssg) == SOCKET_ERROR) {
- std::cout << "Odosielanie zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- if ((recv_mssg_len = recvfrom(st, signal, sizeof(MESS), 0, (SADDR*)&client, &from_mssg_len)) == SOCKET_ERROR) {
- std::cout << "Prijem SYNACK zlyhal, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- std::this_thread::sleep_for(std::chrono::milliseconds(roundTT + 50000));
- }
- }
- unsigned short getCRC(char *data_p, unsigned short length) {
- unsigned char i;
- unsigned int data;
- unsigned int crc = 0xffff;
- if (length == 0)
- return (~crc);
- do
- {
- for (i = 0, data = (unsigned int)0xff & *data_p++;
- i < 8;
- i++, data >>= 1)
- {
- if ((crc & 0x0001) ^ (data & 0x0001))
- crc = (crc >> 1) ^ POLY;
- else crc >>= 1;
- }
- } while (--length);
- crc = ~crc;
- data = crc;
- crc = (crc << 8) | (data >> 8 & 0xff);
- return (crc);
- }
- void vypisPaket(MESS *received, char *start_data) {
- std::cout << "CRC:" << received->crc << ": " << start_data << std::endl;
- std::cout << "Velkost fragmentu: " << received->length;
- std::cout << " poradie: " << received->kolkaty << "/" << received->numOfFrags << std::endl;
- std::cout << "Flag: " << received->flag << std::endl << "--------------------------------------------" << std::endl;
- }
- void clear_field(char *field, int len) {
- for (int i = 0; i < len; i++) {
- field[i] = 0;
- }
- }
- bool check_packet(MESS *packet) {
- if (packet->crc != getCRC((char*)packet + sizeof(short), sizeof(MESS) + packet->length - sizeof(short))) {
- std::cout << "CRC sa nezhoduje, vyratane:" << getCRC((char*)packet + sizeof(short), sizeof(MESS) + packet->length - sizeof(short)) << std::endl;
- return FALSE;
- }
- else
- std::cout << "CRC ok" << std::endl;
- return TRUE;
- }
- void server_startup(int port) {
- int from_mssg_len, recv_mssg_len;
- int FRAGMAX = 0;
- bool connection_established = FALSE;
- WSADATA socketStruct;
- if (WSAStartup(MAKEWORD(2, 2), &socketStruct)) {
- std::cout << "Nepodarilo sa spustit WSADATA, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- //otvorenie socketu, AF_INET - IPv4 adresy, SOCK_DGRAM - UDPcko
- SOCKET sd = socket(AF_INET, SOCK_DGRAM, 0);
- if (sd == INVALID_SOCKET) {
- std::cout << "Socket nemohol byt otvoreny, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- SADDRIN server, client;
- server.sin_family = AF_INET; //IPv4 adresy
- server.sin_addr.s_addr = INADDR_ANY;
- server.sin_port = htons(port);
- from_mssg_len = sizeof(client);
- //bindnutie socketu
- if (bind(sd, (SADDR*)&server, sizeof(server)) == SOCKET_ERROR) {
- std::cout << "Nepodarilo sa nabindovat socket, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- std::cout << "Spusta sa server.." << std::endl;
- MESS *received, *send;
- char *start_data, *mssg = (char*)malloc(sizeof(MESS) * sizeof(char) + MSSG_LEN);
- char *send_flag = (char*)malloc(sizeof(MESS) * sizeof(char));
- clear_field(mssg, sizeof(MESS) * sizeof(char) + MSSG_LEN);
- clear_field(send_flag, sizeof(MESS) * sizeof(char));
- char **entire_message = NULL;
- //4-way handshake vlastna
- if ((recv_mssg_len = recvfrom(sd, mssg, sizeof(MESS) * sizeof(char) + MSSG_LEN, 0, (SADDR*)&client, &from_mssg_len)) == SOCKET_ERROR) {
- std::cout << "Prijem SYN zlyhal, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- received = (MESS*)mssg;
- //prijal som SYN
- if (received->flag == 1) {
- //odosielam SYNACK
- send = (MESS*)send_flag;
- send->flag = 2;
- if (sendto(sd, send_flag, sizeof(MESS) * sizeof(char), 0, (SADDR*)&client, from_mssg_len) == SOCKET_ERROR) {
- std::cout << "Odosielanie SYNACK zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- clear_field(mssg, sizeof(MESS) * sizeof(char) + MSSG_LEN);
- //prijimam ACK
- if ((recv_mssg_len = recvfrom(sd, mssg, sizeof(MESS) * sizeof(char) + MSSG_LEN, 0, (SADDR*)&client, &from_mssg_len)) == SOCKET_ERROR) {
- std::cout << "Prijimanie ACK zlyhalo, error:" << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- received = (MESS*)mssg;
- if (received->flag == 3) {
- //nastavit FRAGMAX
- FRAGMAX = received->length;
- //posielam ACK
- send->flag = 3;
- if (sendto(sd, send_flag, sizeof(MESS) * sizeof(char), 0, (SADDR*)&client, from_mssg_len) == SOCKET_ERROR) {
- std::cout << "Odosielanie ACK zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- std::cout << "Prebehla 4-way autorizacia\n";
- connection_established = TRUE;
- }
- }
- //pocuvam na sockete
- std::cout << "Pripraveny na prijem dat\n" << std::endl;
- while (connection_established) {
- fflush(stdout);
- memset(mssg, '\0', sizeof(MESS) * sizeof(char) + MSSG_LEN);
- if ((recv_mssg_len = recvfrom(sd, mssg, sizeof(MESS) * sizeof(char) + MSSG_LEN, 0, (SADDR*)&client, &from_mssg_len)) == SOCKET_ERROR) {
- std::cout << "Prijem dat zlyhal, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- received = (MESS*)mssg;
- start_data = mssg + sizeof(MESS);
- if (check_packet(received) == FALSE) {
- //paket prisiel poskodeny, znovu vyziadaj paket
- send = (MESS*)send_flag;
- send->flag = 7;
- std::cout << "Paket prisiel poskodeny, vyzadujem znovuzaslanie\n" << "-------" << std::endl;
- if (sendto(sd, send_flag, sizeof(MESS) * sizeof(char), 0, (SADDR*)&client, from_mssg_len) == SOCKET_ERROR) {
- std::cout << "Odosielanie Znovuvyziadania zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- continue;
- }
- if (received->flag == 6) {
- //ak ide iba o ping, resp. keep alive signal; odpovedz ACK
- send = (MESS*)send_flag;
- send->flag = 3;
- if (sendto(sd, send_flag, sizeof(MESS) * sizeof(char), 0, (SADDR*)&client, from_mssg_len) == SOCKET_ERROR) {
- std::cout << "Odosielanie Znovuvyziadania zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- std::cout << "Dorazil keep alive signal\n" << "--------------------------------------------" << std::endl;
- continue;
- }
- if (received->numOfFrags > 1) {
- //ideme spajat fragmenty
- //ak idem spravit novy zaznam
- if (entire_message == NULL) {
- entire_message = (char**)malloc(received->numOfFrags * sizeof(char*));
- for (int i = 0; i < received->numOfFrags; i++) {
- entire_message[i] = (char*)malloc(FRAGMAX * sizeof(char));
- }
- }
- //spracovavam spravu
- strcpy(entire_message[received->kolkaty - 1], start_data);
- }
- if (received->flag == 5) {
- //potvrd ze paket prisiel v poriadku, ak ide o textovu spravu
- clear_field(send_flag, sizeof(MESS));
- send = (MESS*)send_flag;
- send->flag = 3;
- if (sendto(sd, send_flag, sizeof(MESS), 0, (SADDR*)&client, from_mssg_len) == SOCKET_ERROR) {
- std::cout << "Odosielanie Znovuvyziadania zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- }
- if (strstr(start_data, "stop") != NULL) {
- std::cout << "Server je ukonceny" << std::endl;
- //poslat ack na client ze sa moze vypnut
- break;
- }
- vypisPaket(received, start_data);
- //ak mam uz posledny paket, vypisem cele pole a uvolnim ho
- if (entire_message != NULL && received->kolkaty == received->numOfFrags) {
- std::cout << "Cela sprava: ";
- for (int i = 0; i < received->numOfFrags; i++) {
- printf("%s", entire_message[i]);
- }
- std::cout << std::endl << std::endl;
- entire_message = NULL;
- }
- std::cout << std::endl;
- }
- closesocket(sd);
- WSACleanup();
- }
- void client_startup(int port, char* server_ip, int FRAGMAX) {
- WSADATA socketStruct;
- bool connection_established = FALSE;
- char *file_name;
- if (WSAStartup(MAKEWORD(2, 2), &socketStruct) != 0) {
- std::cout << "Neinicializovala sa struktura socketu!";
- exit(EXIT_FAILURE);
- }
- SOCKET st = socket(AF_INET, SOCK_DGRAM, 0);
- if (st == INVALID_SOCKET) {
- std::cout << "Socket nemohol byt otvoreny, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- SADDRIN client;
- int recv_mssg_len, from_mssg_len = sizeof(client);
- memset((char *)&client, 0, sizeof(client));
- client.sin_family = AF_INET;
- client.sin_port = htons(port);
- client.sin_addr.S_un.S_addr = inet_addr(server_ip);
- int size_mssg = sizeof(client);
- std::cout << "Spustil sa klient" << std::endl;
- char vstup[MSSG_LEN];
- char *mssg = (char*)malloc(sizeof(char)), *input;
- int pocet_fragmentov;
- //moja 4-way handshake
- mssg = (char*)realloc(mssg, sizeof(MESS) * sizeof(char));
- MESS *syn = (MESS*)mssg;
- syn->flag = 1;
- syn->length = FRAGMAX;
- //posli SYN
- if (sendto(st, mssg, sizeof(MESS) * sizeof(char), 0, (SADDR*)&client, size_mssg) == SOCKET_ERROR) {
- std::cout << "Odosielanie SYN zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- //prijimam SYNACK
- char recv_flag[sizeof(MESS)];
- if ((recv_mssg_len = recvfrom(st, recv_flag, sizeof(MESS) * sizeof(char), 0, (SADDR*)&client, &from_mssg_len)) == SOCKET_ERROR) {
- std::cout << "Prijem SYNACK zlyhal, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- syn = (MESS*)recv_flag;
- if (syn->flag == 2) {
- //posli ACK 3
- syn = (MESS*)mssg;
- syn->flag = 3;
- syn->length = FRAGMAX;
- if (sendto(st, mssg, sizeof(MESS) * sizeof(char), 0, (SADDR*)&client, size_mssg) == SOCKET_ERROR) {
- std::cout << "Odosielanie ACK pri SYN zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- memset(recv_flag, '\0', sizeof(MESS));
- if ((recv_mssg_len = recvfrom(st, recv_flag, sizeof(MESS) * sizeof(char), 0, (SADDR*)&client, &from_mssg_len)) == SOCKET_ERROR) {
- std::cout << "Prijem ACK zlyhal, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- syn = (MESS*)recv_flag;
- if (syn->flag == 3) {
- //ak som prijal ACK, handshake prebehol uspesne
- std::cout << "Prebehol 4way handshake - uspesne." << std::endl;
- std::cout << "Klient pripraveny na posielanie sprav" << std::endl;
- connection_established = TRUE;
- }
- }
- std::cout << "Program vyuziva klucove slova, ktore staci zadat do textu spravy, su to\n\tbad +text- do textu zamerne vnesie chybu a odosle chybny ramec\n\t";
- std::cout << "stop - ukonci komunikaciu na oboch stranach (server aj klient)\n\tfile - prenesie textovy dokument, po zadani bude treba uviest nazov suboru.\n\n";
- //spustenie threade na keep alive signaly
- std::thread alive(concurent_alive, st, client, size_mssg);
- alive.detach();
- while (connection_established) {
- clear_field(vstup, MSSG_LEN);
- std::cout << "\nZadaj spravu: ";
- std::cin.getline(vstup, MSSG_LEN);
- if (strstr(vstup, "file") != NULL) {
- std::cout << "Funkcionalita zatial nie je implementovana\n";
- }
- int input_len = strlen(vstup), frag_len = 0;
- pocet_fragmentov = (strlen(vstup) / FRAGMAX) + 1;
- for (int i = 0; i < pocet_fragmentov; i++) {
- if (input_len - FRAGMAX >= 0) {
- input_len -= FRAGMAX;
- frag_len = FRAGMAX;
- }
- else {
- frag_len = input_len;
- }
- mssg = (char*)realloc(mssg, sizeof(MESS) * sizeof(char) + frag_len);
- memset(mssg, '\0', sizeof(MESS) * sizeof(char) + frag_len);
- MESS *send = (MESS*)mssg;
- input = mssg + sizeof(MESS);
- strncpy(input, vstup + i*FRAGMAX, frag_len);
- send->length = frag_len;
- send->kolkaty = i + 1;
- send->numOfFrags = pocet_fragmentov;
- send->flag = 5;
- send->crc = getCRC((char*)send + sizeof(short), sizeof(MESS) + send->length - sizeof(short));
- if (strstr(vstup, "bad") != NULL) {
- //vnasam chybu
- send->flag = 100;
- }
- std::cout << "#" << i << ". fragment ";
- for (int j = 0; j < frag_len; j++) {
- printf("%c", input[j]);
- }
- std::cout << std::endl;
- if (sendto(st, mssg, sizeof(MESS) * sizeof(char) + frag_len, 0, (SADDR*)&client, size_mssg) == SOCKET_ERROR) {
- std::cout << "Odosielanie zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- memset(recv_flag, '\0', sizeof(MESS));
- while (1) {
- if ((recv_mssg_len = recvfrom(st, recv_flag, sizeof(MESS) * sizeof(char), 0, (SADDR*)&client, &from_mssg_len)) == SOCKET_ERROR) {
- std::cout << "Prijem ACK zlyhal, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- syn = (MESS*)recv_flag;
- if (syn->flag == 3) {
- break;
- }
- else {
- //paket prisiel poskodeny, posielam ho znovu, opraveny
- send->flag = 5;
- send->crc = getCRC((char*)send + sizeof(short), sizeof(MESS) + send->length - sizeof(short));
- if (sendto(st, mssg, sizeof(MESS) * sizeof(char) + frag_len, 0, (SADDR*)&client, size_mssg) == SOCKET_ERROR) {
- std::cout << "Odosielanie nahradneho paketu zlyhalo, error: " << WSAGetLastError << std::endl;
- exit(EXIT_FAILURE);
- }
- }
- }
- }
- if (strstr(vstup, "stop") != NULL) {
- std::cout << "Klient je ukonceny" << std::endl;
- LOCK = FALSE;
- //poslat fin flag na server ze sa moze vypnut
- break;
- }
- }
- closesocket(st);
- WSACleanup();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement