Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Server
- #pragma comment(lib,"ws2_32.lib")
- #include <WS2tcpip.h>
- #include <iostream>
- #include <bitset>
- #include <sstream>
- #include <string>
- #include <vector>
- int convertBinaryToDecimal(long long n)
- {
- int decimalNumber = 0, i = 0, remainder;
- while (n != 0)
- {
- remainder = n % 10;
- n /= 10;
- decimalNumber += remainder*pow(2, i);
- ++i;
- }
- return decimalNumber;
- }
- // Done ale brzydko V
- std::string zamianaBND(std::string x)
- {
- int n = stoi(x);
- n = convertBinaryToDecimal(n);
- x = std::to_string(n);
- return x;
- }
- //DoneVVV
- std::string zamianaDNB(std::string x)
- {
- int number = stoi(x);
- std::bitset<16> mySet(number);
- x = mySet.to_string();
- x.erase(0, min(x.find_first_not_of('0'), x.size() - 1));
- return x;
- }
- //Z tego jestem tak dumny V xd
- std::string zamianaSNB(std::string x) //string
- {
- std::string wynik;
- for (std::size_t i = 0; i < x.size(); ++i)
- {
- std::stringstream stream;
- stream << std::bitset<8>(x[i]);
- wynik += stream.str();
- }
- return wynik;
- }
- std::string zamianaBNS(std::string data)
- {
- std::stringstream sstream(data);
- std::string output;
- while (sstream.good())
- {
- std::bitset<8> bits;
- sstream >> bits;
- char c = char(bits.to_ulong());
- output += c;
- }
- return output;
- }
- std::string encodeBitsToBaits(std::string inputDatagramInBits)
- {
- // Dopelnienie zerami, jesli jest taka potrzeba
- while (inputDatagramInBits.size() % 8 != 0)
- {
- inputDatagramInBits.push_back('0');
- }
- // Po uzupelnieniu pakiet jest gotowy do zamiany na bajty
- int datagramLength = inputDatagramInBits.size();
- char bait = 0; // Zmienna bait bedzie zapisywala kolejne osemki bitow
- std::string datagramInBaits; // PakietBajtow to gotowy lancuch bajtow
- int operationIndex = 0; // Zmienna OperationIndeks jest niezbedna przy operacjach na bitach
- // Zmienna i wskazuje na pierwszy bit z danej osemki bitow
- for (int i = 0; i < datagramLength; i += 8)
- {
- bait = 0;
- operationIndex = 0;
- // Zmienna j iteruje po osmiu kolejnych bitach zaczynajac od bitu i. Jesli bit jest jedynka, to jedynka zostaje przesunieta na odpowiednia pozycje
- for (int j = i; j < i + 8; ++j)
- {
- if (inputDatagramInBits[j] == '1')
- {
- bait = bait | 1 << (7 - operationIndex);
- }
- operationIndex++;
- }
- // Dopisanie gotowego bajtu danych do zmiennej datagramInBaits
- datagramInBaits.push_back(bait);
- }
- // Zwrocenie datagramu, w ktorym kazdy znak zapisuje 8 bitow
- return datagramInBaits;
- }
- std::string decodeBaitsToBits(std::string inputDatagramInBaits)
- {
- std::string datagramInBits;
- std::string bits;
- // Zmienna i iteruje po kolejnych bajtach az do konca lancucha znakow
- for (int i = 0; i < inputDatagramInBaits.size(); i++)
- {
- bits.clear();
- // Zapisanie danego znaku jako liczby i zapisanie tej liczby do bitset
- int charAsInteger = inputDatagramInBaits[i];
- std::bitset<8> mySet(charAsInteger);
- // Zapisanie danego bajtu jako ciagu zer i jedynek o dlugosci 8 do zmiennej bits
- bits = mySet.to_string();
- //Dopisanie osmiu zer i jedynek do wynikowego datagramu
- datagramInBits += bits;
- }
- //Zwrocenie datagramu, w ktorym kazdy znak ma wartosc 1 lub 0
- return datagramInBits;
- }
- std::string poprawnyOdbior(char input[4096])
- {
- std::string temp;
- std::string odpowiedz;
- std::string rozmiarBin;
- std::string jedynaslusznaodpowiedz;
- int rozmiarDec;
- int rozmiarCalegoPakietuWBajtach;
- for (int i = 0; i < 9; i++)
- {
- temp += input[i];
- }
- temp = decodeBaitsToBits(temp);
- for (int i = 5; i <= 68; i++)
- {
- rozmiarBin += temp[i];
- }
- rozmiarDec = stoi(zamianaBND(rozmiarBin));
- rozmiarCalegoPakietuWBajtach = ((68 + rozmiarDec) / 8);
- if (((68 + rozmiarDec)%8) > 0) rozmiarCalegoPakietuWBajtach += 1;
- for (int i = 0; i < rozmiarCalegoPakietuWBajtach; i++)
- {
- odpowiedz += input[i];
- }
- jedynaslusznaodpowiedz = decodeBaitsToBits(odpowiedz);
- while (jedynaslusznaodpowiedz.size() > (69 + rozmiarDec))
- {
- jedynaslusznaodpowiedz.pop_back();
- }
- return jedynaslusznaodpowiedz;
- }
- void prepare(std::string &buff, std::string toSend)
- {
- buff.erase(buff.begin() + 77, buff.end()); // wywalamy stare dane
- int number = toSend.size() ;
- std::string rozmiar;
- std::bitset<64> mySet(number + 8);
- rozmiar = mySet.to_string(); // tu ustawiamy pole dlugosci danych w 64 bitach
- for (int i = 0; i < 64; ++i) {
- buff[5 + i] = rozmiar[i]; // zapisujemy ten rozmiar w pliku
- }
- for (int i = 0; i < number; ++i) // zapisujemy dane do wyslania
- {
- buff.push_back(toSend[i]);
- } //tu zapisuje dane na ich polu
- std::string temporary = encodeBitsToBaits(buff);
- buff = temporary;
- }
- void prepare1(std::string &buff, std::string toSend)
- {
- //buff.erase(buff.begin() + 75, buff.end()); // wywalamy stare dane
- int number = toSend.size();
- std::string rozmiar;
- std::bitset<64> mySet(number);
- rozmiar = mySet.to_string(); // tu ustawiamy pole dlugosci danych w 64 bitach
- for (int i = 0; i < 64; ++i) {
- buff[5 + i] = rozmiar[i]; // zapisujemy ten rozmiar w pliku
- }
- for (int i = 0; i < number; ++i) // zapisujemy dane do wyslania
- {
- buff.push_back(toSend[i]);
- } //tu zapisuje dane na ich polu
- std::string temporary = encodeBitsToBaits(buff);
- buff = temporary;
- }
- // Obliczanie silni. Jesli zakres zostanie przekroczony, funkcja zapisuje w isError wartosc 2
- int silnia(int x, int &isError)
- {
- int potega = 1;
- for (int i = 1; i <= x; i++) {
- potega *= i;
- if (potega < 0)
- {
- isError = 2;
- return 0;
- }
- }
- return potega;
- }
- void main()
- {
- // Initialize Winsock
- WSAData wsaData;
- WORD DllVersion = MAKEWORD(2, 1);
- if (WSAStartup(DllVersion, &wsaData) != 0)
- {
- std::cout << "Nie mozna uruchomic Winsock" << std::endl;
- return;
- }
- // Create socket
- SOCKET listening = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //odpowiedzialny za nasluchiwanie(address family that is used to designate the type of addresses that your socket can communicate with (in this case, Internet Protocol v4 addresses), (TCP))
- if (listening == INVALID_SOCKET)
- {
- std::cout << "Nie mozna stworzyc Wincosk" << std::endl;
- return;
- }
- // Bind the ip address and port to a socket
- sockaddr_in hint;
- hint.sin_family = AF_INET;//IPv4
- hint.sin_port = htons(8888);//host to network short - rozwiazuje problemy z big i little indian, port
- hint.sin_addr.s_addr = INADDR_ANY; //tu idzie adres IP
- bind(listening, (sockaddr*)&hint, sizeof(hint));
- // Wait for a connection
- sockaddr_in client;
- int clientSize = sizeof(client);
- //SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize); //jakie polaczenia akceptujemy
- // Close listening socket
- // closesocket(listening);
- // While loop: accept and echo message back to client
- char buff[4096];//rozmiar bufora
- int sesja = 0;
- struct wpis
- {
- int nrSesji;
- std::string operacja;
- };
- std::vector<wpis> historia;
- std::string stringSesji; // ================================== dodalem string sesji
- while (true)
- {
- ZeroMemory(buff, 4096);
- // Wait for client to send data
- int bytesRecieved = recvfrom(listening, buff, 4096, 0, (struct sockaddr *) &client, &clientSize); //rozmiar danych otrzymanych na serwerze
- std::string odebraneDane = poprawnyOdbior(buff);
- std::cout << bytesRecieved << std::endl;
- if (bytesRecieved == SOCKET_ERROR)
- {
- std::cout << "Error in recv(). Quitting" << std::endl;
- continue;
- }
- if (bytesRecieved == 0)
- {
- std::cout << "Client disconnected " << std::endl;
- continue;
- }
- // S T A R T
- int wynik;
- std::string number = odebraneDane; //hehe (getit string a to numer xD xD xD dobre bardzo)
- // 4 - 67
- std::string dane; // tu sobie je na dziesietne zrobie bo moge
- for (int i = 5; i < 69; i++)
- {
- dane.push_back(number[i]);
- }
- dane = zamianaBND(dane);
- int rozmiarDanych = stoi(dane);
- dane = "";
- //if (rozmiarDanych)
- //{
- // for (int i = 0; i < rozmiarDanych - 8; i++)
- // {
- // dane += number[77 + i];
- // }
- // dane = zamianaBNS(dane);
- // rozmiarDanych = dane.size() - 1; // znak konca sie tez zalicza przez te glupie chary
- //}
- // Operacja 00 - polaczenie
- if (number[0] == '0' && number[1] == '0')
- {
- // Status 000 - pierwsze polaczenie, zadanie przydzielenia numeru sesji
- if (number[2] == '0' && number[3] == '0' && number[4] == '0')
- {
- sesja++;
- std::string old_string = std::to_string(sesja);
- old_string = zamianaDNB(old_string);
- std::string new_string = std::string(6 - old_string.length(), '0') + old_string; // z 1 robi 00000001 etc
- std::string daneDoWyslania;
- for (int i = 0; i < new_string.length(); i++)
- {
- daneDoWyslania.push_back(new_string[i]);
- }
- number[2] = '1';
- number[3] = '0';
- number[4] = '1';
- stringSesji = daneDoWyslania; // ================================================== zapisuje numer sesji w string sesji
- prepare1(number, daneDoWyslania);
- sendto(listening, number.c_str(), number.size() + 1, 0, (struct sockaddr *) &client, clientSize);
- }
- if (number[2] == '1' && number[3] == '1' && number[4] == '1')
- {
- std::cout << "Odebrano operacje 00 o statusie 111 - klient zakonczyl polaczenie." << std::endl;
- continue;
- }
- }
- //Operacja 01 - silnia
- else if (number[0] == '0' && number[1] == '1')
- {
- for (int i = 0; i < rozmiarDanych - 6; i++)
- {
- dane += number[75 + i];
- }
- dane = zamianaBNS(dane);
- rozmiarDanych = dane.size() - 1; // znak konca sie tez zalicza przez te glupie chary
- int isError = 0; // Zmienna okreslajaca blad w dzialaniach: 0 - OK, 1 - Blad Klienta, 2 - overflow
- std::string a;
- for (int i = 0; i < rozmiarDanych; i++)
- {
- a.push_back(dane[i]);
- }
- // Obliczenie silni dla podanej liczby
- int b = stoi(a);
- wynik = silnia(b, isError);
- // Zapisanie wyniku dzialania do historii obliczen
- wpis tmp;
- tmp.nrSesji = sesja;
- tmp.operacja = "Silnia z " + a + " wynosi " + std::to_string(wynik);
- historia.push_back(tmp);
- std::string toSend;
- if (isError == 0)
- {
- // Przygotowanie danych do wyslania
- toSend = std::to_string(wynik);
- toSend = zamianaDNB(toSend);
- //Ustawienie statusu na 101 - prawidlowa odpowiedz
- number[2] = '1';
- number[3] = '0';
- number[4] = '1';
- prepare(number, toSend);
- }
- else if (isError == 1)
- {
- // Przygotowanie danych do wyslania
- toSend = "";
- toSend = zamianaDNB(toSend);
- //Ustawienie statusu na 001 - blad po stronie klienta
- number[2] = '0';
- number[3] = '0';
- number[4] = '1';
- prepare(number, toSend);
- }
- else if (isError == 2)
- {
- // Przygotowanie danych do wyslania
- toSend = "";
- toSend = zamianaDNB(toSend);
- //Ustawienie statusu na 100 - przekroczenie zakresu zmiennej
- number[2] = '1';
- number[3] = '0';
- number[4] = '0';
- prepare(number, toSend);
- }
- else { std::cout << "Nieznany blad serwera" << std::endl; }
- //Odeslanie wyniku dzialania/bledu do klienta
- sendto(listening, number.c_str(), number.size() + 1, 0, (struct sockaddr *) &client, clientSize);
- }
- // Operacja 10 - dzialanie na 2 argumentach
- else if(number[1] == '0' && number[0] == '1')
- {
- for (int i = 0; i < rozmiarDanych - 8; i++)
- {
- dane += number[77 + i];
- }
- dane = zamianaBNS(dane);
- rozmiarDanych = dane.size() - 1; // znak konca sie tez zalicza przez te glupie chary
- // Status 110 - zadanie klienta
- if (number[2] == '1' && number[3] == '1' && number[4] == '0')
- {
- int isError = 0; // Zmienna okreslajaca blad w dzialaniach: 0 - OK, 1 - Blad Klienta, 2 - overflow
- if (number.size() < 79) {
- isError = 1;
- std::cout << "Blad klienta";
- }
- // Dzialanie 00 - mnozenie 2 liczb
- if (number[75] == '0' && number[76] == '0')
- {
- std::string a, b;
- int ktory = 0;
- // Podzial danych na liczby a i b oddzielone spacja
- for (int i = 0; i < rozmiarDanych; i++)
- {
- if (ktory == 0)
- {
- if (dane[i] != ' ') { a.push_back(dane[i]); }
- else { ktory++; }
- }
- else { b.push_back(dane[i]); }
- }
- // Obliczenie wyniku
- wynik = stoi(a) * stoi(b);
- // Sprawdzenie, czy nie przekroczono zakresu zmiennej
- if (stoi(a) != 0 && wynik / stoi(a) != stoi(b)) {
- isError = 2;
- }
- //Wpisanie dzialania do historii
- wpis tmp;
- tmp.nrSesji = sesja;
- tmp.operacja = a + " * " + b + " = " + std::to_string(wynik);
- historia.push_back(tmp);
- }
- // Dzialanie 01 - dzielenie 2 liczb
- if (number[75] == '0' && number[76] == '1')
- {
- std::string a, b;
- int ktory = 0;
- // Podzial danych na liczby a i b oddzielone spacja
- for (int i = 0; i < rozmiarDanych; i++)
- {
- if (ktory == 0)
- {
- if (dane[i] != ' ') { a.push_back(dane[i]); }
- else { ktory++; }
- }
- else { b.push_back(dane[i]); }
- }
- wynik = stoi(a) / stoi(b);
- wpis tmp;
- tmp.nrSesji = sesja;
- tmp.operacja = a + " / " + b + " = " + std::to_string(wynik);
- historia.push_back(tmp);
- }
- // Dzialanie 10 - dodawanie 2 liczb
- if (number[75] == '1' && number[76] == '0')
- {
- std::string a, b;
- int ktory = 0;
- // Podzial danych na liczby a i b oddzielone spacja
- for (int i = 0; i < rozmiarDanych; i++)
- {
- if (ktory == 0)
- {
- if (dane[i] != ' ') { a.push_back(dane[i]); }
- else { ktory++; }
- }
- else { b.push_back(dane[i]); }
- }
- // Obliczenie wyniku
- wynik = stoi(a) + stoi(b);
- // Sprawdzenie, czy nie przekroczono zakresu zmiennej
- if (wynik - stoi(a) != stoi(b)) {
- isError = 2;
- }
- //Wpisanie dzialania do historii
- wpis tmp;
- tmp.nrSesji = sesja;
- tmp.operacja = a + " + " + b + " = " + std::to_string(wynik);
- historia.push_back(tmp);
- }
- // Dzialanie 11 - odejmowanie 2 liczb
- if (number[75] == '1' && number[76] == '1')
- {
- std::string a, b;
- int ktory = 0;
- // Podzial danych na liczby a i b oddzielone spacja
- for (int i = 0; i < rozmiarDanych; i++)
- {
- if (ktory == 0)
- {
- if (dane[i] != ' ') { a.push_back(dane[i]); }
- else { ktory++; }
- }
- else { b.push_back(dane[i]); }
- }
- // Obliczenie wyniku
- wynik = stoi(a) - stoi(b);
- // Sprawdzenie, czy nie przekroczono zakresu zmiennej
- if (wynik + stoi(b) != stoi(a)) {
- isError = 2;
- }
- //Wpisanie dzialania do historii
- wpis tmp;
- tmp.nrSesji = sesja;
- tmp.operacja = a + " - " + b + " = " + std::to_string(wynik);
- historia.push_back(tmp);
- }
- //Koniec dzialan - przygotowanie danych do wyslania
- std::string toSend;
- if (isError == 0)
- {
- toSend = std::to_string(wynik);
- toSend = zamianaDNB(toSend);
- // Ustawienie statusu na 101 - poprawne zwrocenie zasobow
- number[2] = '1';
- number[3] = '0';
- number[4] = '1';
- prepare(number, toSend);
- }
- else
- {
- toSend = "";
- // Ustawienie statusu na 010 - blad po stronie serwera
- number[2] = '0';
- number[3] = '1';
- number[4] = '0';
- prepare(number, toSend);
- }
- //Odeslanie wyniku dzialania/bledu do klienta
- sendto(listening, number.c_str(), number.size() + 1, 0, (struct sockaddr *) &client, clientSize);
- }
- }
- } // Koniec petli while(true)
- // Close
- closesocket(listening);
- // Cleanup Winsock
- WSACleanup();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement