Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // UDPServer.cpp : Defines the entry point for the console application.
- //
- #include "stdafx.h"
- #include <iostream>
- #include <stdlib.h>
- #include <winsock.h>
- #include <bitset>
- #include <limits.h>
- #include <vector>
- #include <algorithm>
- #include <math.h>
- #include <queue>
- #include <thread>
- #include <list>
- #pragma comment(lib, "Ws2_32.lib")
- #define SERVERPORT 4950
- #define CLIENTPORT 4951
- class Packet {
- int operation; //bity 0-1
- int number1; //bity 2-64
- int number2; //bity 2-64
- int number3; //bity 2-64
- int status; //bity 65-69
- int id; //bity 70-73
- int sizeNumber1; //bity 74-78
- int sizeNumber2; //bity 79-83
- int sizeNumber3; //bity 84-88
- std::bitset<89> binaryData;
- unsigned char packet[12];
- public:
- Packet() {
- operation = 0;
- number1 = 0;
- number2 = 0;
- number3 = 0;
- status = 0;
- id = 0;
- sizeNumber1 = 0;
- sizeNumber2 = 0;
- sizeNumber3 = 0;
- }
- private:
- //obliczanie wielkosci liczby w bitach
- int bitSize(int number) {
- int size = 0;
- while (number >= 1) {
- ++size;
- number /= 2;
- }
- return size;
- }
- //zamiana liczb na postac binarna i wstawienie ich do bitset
- void setBits(int number, int startingBit, int size) {
- std::vector<int> binary;
- while (number >= 1) {
- binary.push_back(number % 2);
- number /= 2;
- }
- while (binary.size() < size)binary.push_back(0); //dodaj przednie 0
- std::reverse(binary.begin(), binary.end());
- for (int i = 0; i < binary.size(); i++) {
- binaryData[startingBit + i] = binary[i];
- if (startingBit == binaryData.size() - 1)break; //jezeli to ostatni bit pakietu, przerwij petle
- }
- }
- //zamiana z postaci binarnej na dziesietna
- void decodeBits(int &number, int startingBit, int size) {
- int power = size - 1;
- int currentBit = startingBit;
- number = 0;
- for (int i = 0; i < size; i++) {
- if (binaryData[currentBit] == 1)
- number += pow(2, power - i);
- currentBit++;
- }
- }
- //tworzenie pakietu do wyslania
- void packThePacket() {
- for (int i = 0; i < 12; i++)packet[i] = 0;
- int currentPart = 0, bitValue = 0, bitCounter = 0, power = 7;
- for (int i = 0; i < binaryData.size(); i++) {
- bitValue = binaryData[i];
- if (bitValue == 1)packet[currentPart] += pow(2, power);
- power--;
- bitCounter++;
- if (bitCounter == 8) {
- bitCounter = 0;
- currentPart++;
- power = 7;
- }
- }
- }
- void unpackThePacket() {
- for (int i = 0; i < 12; i++) setBits(packet[i], i * 8, 8);
- }
- public:
- //tworzenie pakietu, zamiana z postaci dziesietnej na postac binarna wartosci pakietu oraz pakowanie do wyslania
- void createPacket() {
- setBits(operation, 0, 2); //bity 0-1
- setBits(number1, 2, sizeNumber1); //bity 2-65
- setBits(number2, 2 + sizeNumber1, sizeNumber2); //bity 2-65
- setBits(number3, 2 + sizeNumber1 + sizeNumber2, sizeNumber3); //bity 2-65
- setBits(status, 66, 4); //bity 66-69
- setBits(id, 70, 4); //bity 70-73
- setBits(sizeNumber1, 74, 5); //bity 74-78
- setBits(sizeNumber2, 79, 5); //bity 79-83
- setBits(sizeNumber3, 84, 5); //bity 84-88
- packThePacket();
- }
- void decodePacket(unsigned char* packet) {
- setPacket(packet); //wczytanie przeslanego pakietu
- unpackThePacket(); //rozpakowanie pakietu do postaci binarnej
- //zamiana wartosci binarnej na wartosci dziesietne
- decodeBits(operation, 0, 2); //bity 0-1
- decodeBits(sizeNumber1, 74, 5); //bity 74-78
- decodeBits(sizeNumber2, 79, 5); //bity 79-83
- decodeBits(sizeNumber3, 84, 5); //bity 84-88
- decodeBits(number1, 2, sizeNumber1); //bity 2-65
- decodeBits(number2, 2 + sizeNumber1, sizeNumber2); //bity 2-65
- decodeBits(number3, 2 + sizeNumber1 + sizeNumber2, sizeNumber3); //bity 2-65
- decodeBits(status, 66, 4); //bity 65-69
- decodeBits(id, 70, 4); //bity 70-73
- }
- //zapisanie przyslanego pakietu
- void setPacket(unsigned char* packet) {
- for (int i = 0; i < 12; i++)this->packet[i] = packet[i];
- }
- //zwrocenie pakietu do przeslania
- void getPacket(unsigned char* packet) {
- for (int i = 0; i < 12; i++)packet[i] = this->packet[i];
- }
- int getOperation() {
- return this->operation;
- }
- int getStatus() {
- return this->status;
- }
- void calculateResult() {
- long long int result;
- if (operation == 0) { //dodawanie
- result = number1 + number2 + number3;
- if (result <= INT_MAX)number1 = result;
- else status = 10; //przepelnienie zmiennej
- }
- if (operation == 1) { //mnozenie
- result = number1*number2*number3;
- if (result <= INT_MAX)number1 = result;
- else status = 10; //przepelnienie zmiennej
- }
- if (operation == 2) { //odejmowanie
- result = number1 - number2 - number3;
- if (result <= INT_MAX)number1 = result;
- else status = 10; //przepelnienie zmiennej
- }
- if (operation == 3) { //dzielenie
- if (number2 != 0 && number3 != 0) {
- result = number1 / number2 / number3;
- if (result <= INT_MAX)number1 = result;
- else status = 10; //przepelnienie zmiennej
- }
- else {
- status = 6; //blad dzielenia przez 0
- }
- }
- if (status != 6 && status != 10) {
- sizeNumber1 = bitSize(number1);
- number2 = 0; //przy zwracaniu wyniku, te wartosci sa nieuzywane
- sizeNumber2 = 0; //przy zwracaniu wyniku, te wartosci sa nieuzywane
- sizeNumber3 = 0; //przy zwracaniu wyniku, te wartosci sa nieuzywane
- number3 = 0; //przy zwracaniu wyniku, te wartosci sa nieuzywane
- status = 3; //ustaw stan na zwracanie wyniku;
- }
- createPacket();
- }
- void setId(int id) {
- this->id = id;
- this->status = 1; //zwrocenie ID sesji klientowi
- createPacket();
- }
- //ustawienie statusu pakietu
- bool setStatus(int status) {
- this->status = status;
- return true;
- }
- int getId() {
- return this->id;
- }
- //zwroc wynik dzialania
- int getProduct() {
- return this->number1;
- }
- int sumNumbers() {
- return number1 + number2 + number3;
- }
- //ustaw wynik dzialania
- void setProduct(int value) {
- this->number1 = value;
- sizeNumber1 = bitSize(number1);
- number2 = 0; //przy zwracaniu wyniku, te wartosci sa nieuzywane
- sizeNumber2 = 0; //przy zwracaniu wyniku, te wartosci sa nieuzywane
- sizeNumber3 = 0; //przy zwracaniu wyniku, te wartosci sa nieuzywane
- number3 = 0; //przy zwracaniu wyniku, te wartosci sa nieuzywane
- status = 3; //ustaw stan na zwracanie wyniku;
- createPacket();
- }
- void showPacket() {
- for (int i = 0; i < binaryData.size(); i++)std::cout << binaryData[i];
- std::cout << std::endl;
- }
- void showStructure() {
- std::cout << operation << " " << number1 << " " << number2 << " " << number3 << " " << status << " " << id << " " << sizeNumber1 << " " << sizeNumber2 << " " << sizeNumber3 << std::endl;
- }
- };
- struct WaitingPacket {
- sockaddr_in client;
- unsigned char packet[12];
- };
- class Connection {
- sockaddr_in client;
- sockaddr_in server;
- WSADATA wsaData;
- SOCKET mainSocket;
- Packet packet;
- std::queue<WaitingPacket>packetBuffor;
- int bytesSent;
- int bytesRecv;
- unsigned char packetRecived[12];
- unsigned char packetSent[12];
- int maxUsers;
- std::list<int> idList;
- int buforWyniku;
- public:
- Connection() {
- memset(&server, 0, sizeof(server));
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = inet_addr("127.0.0.1");
- server.sin_port = htons(SERVERPORT);
- bytesSent = 0;
- bytesRecv = 0;
- maxUsers = 3;
- buforWyniku = 0;
- }
- bool connect() {
- int result = WSAStartup(MAKEWORD(2, 2), &wsaData); //wybor wersji winsock
- if (result != NO_ERROR)
- std::cout << "Blad inicjalizacji" << std::endl;
- mainSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //tworzenie socketu UDP
- if (mainSocket == INVALID_SOCKET)
- {
- std::cout << "Blad podczas tworzenia socketu: " << WSAGetLastError() << std::endl;
- WSACleanup();
- return 0;
- }
- //przypisanie socketu do adresu
- if (bind(mainSocket, (SOCKADDR *)& server, sizeof(client)) == SOCKET_ERROR)
- {
- std::cout << "bind() zakonczony niepoowdzeniem " << std::endl;
- closesocket(mainSocket);
- return 0;
- }
- }
- //sprawdzanie czy ID istnieje na serwerze
- bool checkId(int id) {
- std::list<int>::iterator iter = std::find(idList.begin(), idList.end(), id);
- if (iter != idList.end())return true; //znaleziono id
- else return false; //nie znaleziono id
- }
- int giveId() {
- //szukanie wolnego id
- for (int i = 1; i <= maxUsers; i++)
- if (!checkId(i))return i; //jezeli nie znaleziono to zwroc je
- return 0; //jezeli wszystkie id sa zajete zwroc 0
- }
- void deleteId(int id) {
- idList.remove(id);
- }
- //odbior danych
- void reciveData() {
- int addr_len = sizeof(struct sockaddr);
- WaitingPacket toQueue;
- while (true) {
- bytesRecv = recvfrom(mainSocket, (char*)toQueue.packet, sizeof(toQueue.packet), 0,
- (struct sockaddr *) &toQueue.client, &addr_len);
- packetBuffor.push(toQueue);
- }
- }
- //przeslanie danych
- void sendData() {
- WaitingPacket fromBuffor;
- while (true) {
- if (packetBuffor.size() > 0) {
- fromBuffor = packetBuffor.front();
- packetBuffor.pop();
- packet.decodePacket(fromBuffor.packet);
- int status = packet.getStatus();
- //sprawdzenie poprawnosci id
- if (!checkId(packet.getId()) && status!=0) {
- status = 7; //blad id
- }
- std::cout << "Uzytkownik [" << packet.getId() << "] : ";
- switch (status) {
- case 0: //prosba o id
- if (idList.size() < maxUsers) {
- int id = giveId();
- packet.setId(id); //nadaj id ktorego nie ma jeszcze na liscie
- idList.push_back(id);
- std::cout << "Wysylam ID: " << packet.getId() << " klientowi!" << std::endl;
- }
- else {
- std::cout << "Przekroczono maksymalna ilosc uzytkownikow" << std::endl;
- packet.setStatus(8);
- packet.createPacket();
- }
- break;
- case 2: //wybranie operacji arytmetycznej
- packet.calculateResult();
- std::cout << "Wynik dzialania to: " << packet.getProduct() << std::endl;
- break;
- case 4: //odbieranie wielu liczb do sumowania
- buforWyniku += packet.sumNumbers(); //zapisz wynik do bufora
- std::cout << "Aktualny wynik sumowania to: " << buforWyniku << std::endl;
- break;
- case 5: //ostatnie liczby do dodania
- buforWyniku += packet.sumNumbers();
- packet.setProduct(buforWyniku);
- std::cout << "Ostateczny wynik sumowania to: " << packet.getProduct() << std::endl;
- buforWyniku = 0;
- break;
- case 7: //blad ID
- std::cout << "Nieznane id" << std::endl;
- packet.setStatus(7);
- packet.createPacket();
- break;
- case 9: //Klient zakonczyl polaczenie
- std::cout << "Zakonczenie polaczenia" << std::endl;
- deleteId(packet.getId());
- break;
- default: //nieokreslone
- std::cout << "Niekreslone" << std::endl;
- break;
- }
- //jezeli nie czeka na kolejne liczby lub klient sie nie rozlaczyl, przeslij pakiet
- if (packet.getStatus() != 4 && packet.getStatus() != 9) {
- packet.getPacket(packetSent);
- bytesSent = sendto(mainSocket, (char*)packetSent, sizeof(packetSent), 0,
- (struct sockaddr *) & fromBuffor.client, sizeof(struct sockaddr));
- }
- }
- }
- }
- std::thread reciveThread() {
- return std::thread([this] { reciveData(); });
- }
- std::thread sendThread() {
- return std::thread([this] { sendData(); });
- }
- };
- int main(int argc, char * argv[])
- {
- Connection connection;
- connection.connect();
- std::thread t1 = connection.reciveThread();
- std::thread t2 = connection.sendThread();
- t1.join();
- t2.join();
- system("PAUSE");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement