Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <memory.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <string>
- #include <poll.h>
- #include <vector>
- #include <chrono>
- #include <ctime>
- #include <fstream>
- #include <limits>
- #include <pthread.h>
- #define SERVER_ADDRESS "192.168.1.83"
- #define SERVER_PORT 20200
- #define BUFFER_SIZE 1024
- #define NUMBER_OF_CONNECTIONS 15
- #define WRONG_COMMAND_MESSAGE "Wrong command !!!!!!!!\n"
- #define NO_SUCH_FILE_MESSAGE "Can not find file"
- #define FILE_FOUND_MESSAGE "OK"
- #define QUIT_MESSAGE "disconnect"
- #define ECHO_COMMAND "echo"
- #define TIME_COMMAND "time"
- #define DOWNLOAD_COMMAND "download"
- #define SOCKET_TYPE SOCK_DGRAM
- #define NUM_OF_THREADS_IN_POOL 10
- struct buffers
- {
- std::string inbuf;
- char *outBuf;
- size_t outBufPos;
- size_t outBufLength;
- };
- int sd;
- std::vector<struct pollfd> fds;
- std::vector<struct sockaddr_in> clientAddresses;
- std::vector<struct buffers> sBuffers;
- std::vector<pthread_t> threads(10);
- int lastThread = 0;
- bool pollhup = false;
- void configureServer()
- {
- sd = socket(AF_INET, SOCKET_TYPE, 0);
- struct sockaddr_in address;
- memset(&address, 0, sizeof(sockaddr));
- address.sin_family = AF_INET;
- address.sin_port = htons(SERVER_PORT);
- address.sin_addr.s_addr = inet_addr(SERVER_ADDRESS);
- int rc = bind(sd, (struct sockaddr *)&address, sizeof(address));
- if (rc < 0)
- {
- std::cout << "Bind failed" << std::endl;
- }
- struct pollfd serverFd;
- serverFd.fd = sd;
- serverFd.events = POLLIN;
- fds.push_back(serverFd);
- listen(sd, NUMBER_OF_CONNECTIONS);
- }
- void processData(std::string data, int numberOfSocket)
- {
- bool isSatisfied = false;
- data.erase(data.begin() + data.size() - 1, data.begin() + data.size());
- int spacePos = data.find_first_of(" ");
- std::string command, parameter;
- if (spacePos == std::string::npos)
- {
- command = data;
- parameter = "";
- }
- else
- {
- command = data.substr(0, spacePos);
- parameter = data.substr(spacePos + 1, data.size() - spacePos - 1);
- }
- if (command == ECHO_COMMAND)
- {
- if (parameter != "")
- {
- send(fds[numberOfSocket].fd, parameter.data(), parameter.size(), 0);
- }
- else
- {
- std::string wrongCommandString = WRONG_COMMAND_MESSAGE;
- send(fds[numberOfSocket].fd, wrongCommandString.data(), wrongCommandString.size(), 0);
- }
- isSatisfied = true;
- }
- if (command == TIME_COMMAND)
- {
- if (parameter == "")
- {
- auto timeC = std::chrono::system_clock::now();
- std::time_t time_conv = std::chrono::system_clock::to_time_t(timeC);
- std::string timeStr(std::ctime(&time_conv));
- timeStr.erase(timeStr.begin() + timeStr.size() - 1, timeStr.begin() + timeStr.size());
- send(fds[numberOfSocket].fd, timeStr.data(), timeStr.size(), 0);
- }
- else
- {
- std::string wrongCommandString = WRONG_COMMAND_MESSAGE;
- send(fds[numberOfSocket].fd, wrongCommandString.data(), wrongCommandString.size(), 0);
- }
- isSatisfied = true;
- }
- if (command == DOWNLOAD_COMMAND)
- {
- std::ifstream fin;
- fin.open(parameter, std::ios::binary | std::ios::in);
- if (!fin.is_open())
- {
- std::string noFileMessage = NO_SUCH_FILE_MESSAGE;
- send(fds[numberOfSocket].fd, noFileMessage.data(), noFileMessage.size(), 0);
- }
- else
- {
- std::string fileFoundMessage = FILE_FOUND_MESSAGE;
- send(fds[numberOfSocket].fd, fileFoundMessage.data(), fileFoundMessage.size(), 0);
- fin.ignore(std::numeric_limits<std::streamsize>::max());
- std::streamsize length = fin.gcount();
- fin.clear();
- fin.seekg(0, std::ios_base::beg);
- size_t lengthFile = length;
- char *fileData = (char *)malloc(sizeof(char) * lengthFile);
- fin.read(fileData, lengthFile);
- sBuffers[numberOfSocket - 1].outBuf = fileData;
- sBuffers[numberOfSocket - 1].outBufPos = 0;
- sBuffers[numberOfSocket - 1].outBufLength = lengthFile;
- send(fds[numberOfSocket].fd, &lengthFile, sizeof(size_t), 0);
- }
- fin.close();
- isSatisfied = true;
- }
- if (!isSatisfied)
- {
- std::string wrongCommandString = WRONG_COMMAND_MESSAGE;
- send(fds[numberOfSocket].fd, wrongCommandString.data(), wrongCommandString.size(), 0);
- }
- }
- void processDataUDP(std::string data, int numberOfSocket)
- {
- bool isSatisfied = false;
- data.erase(data.begin() + data.size() - 1, data.begin() + data.size());
- int spacePos = data.find_first_of(" ");
- std::string command, parameter;
- if (spacePos == std::string::npos)
- {
- command = data;
- parameter = "";
- }
- else
- {
- command = data.substr(0, spacePos);
- parameter = data.substr(spacePos + 1, data.size() - spacePos - 1);
- }
- if (command == ECHO_COMMAND)
- {
- if (parameter != "")
- {
- sendto(sd, parameter.data(), parameter.size(), 0, (struct sockaddr *)&clientAddresses[numberOfSocket], sizeof(clientAddresses[numberOfSocket]));
- }
- else
- {
- std::string wrongCommandString = WRONG_COMMAND_MESSAGE;
- sendto(sd, wrongCommandString.data(), wrongCommandString.size(), 0, (struct sockaddr *)&clientAddresses[numberOfSocket], sizeof(clientAddresses[numberOfSocket]));
- }
- isSatisfied = true;
- }
- if (command == TIME_COMMAND)
- {
- if (parameter == "")
- {
- auto timeC = std::chrono::system_clock::now();
- std::time_t time_conv = std::chrono::system_clock::to_time_t(timeC);
- std::string timeStr(std::ctime(&time_conv));
- timeStr.erase(timeStr.begin() + timeStr.size() - 1, timeStr.begin() + timeStr.size());
- sendto(sd, timeStr.data(), timeStr.size(), 0, (struct sockaddr *)&clientAddresses[numberOfSocket], sizeof(clientAddresses[numberOfSocket]));
- }
- else
- {
- std::string wrongCommandString = WRONG_COMMAND_MESSAGE;
- sendto(sd, wrongCommandString.data(), wrongCommandString.size(), 0, (struct sockaddr *)&clientAddresses[numberOfSocket], sizeof(clientAddresses[numberOfSocket]));
- }
- isSatisfied = true;
- }
- if (command == DOWNLOAD_COMMAND)
- {
- std::ifstream fin;
- fin.open(parameter, std::ios::binary | std::ios::in);
- if (!fin.is_open())
- {
- std::string noFileMessage = NO_SUCH_FILE_MESSAGE;
- sendto(sd, noFileMessage.data(), noFileMessage.size(), 0, (struct sockaddr *)&clientAddresses[numberOfSocket], sizeof(clientAddresses[numberOfSocket]));
- }
- else
- {
- std::string fileFoundMessage = FILE_FOUND_MESSAGE;
- sendto(sd, fileFoundMessage.data(), fileFoundMessage.size(), 0, (struct sockaddr *)&clientAddresses[numberOfSocket], sizeof(clientAddresses[numberOfSocket]));
- fin.ignore(std::numeric_limits<std::streamsize>::max());
- std::streamsize length = fin.gcount();
- fin.clear();
- fin.seekg(0, std::ios_base::beg);
- size_t lengthFile = length;
- char *fileData = (char *)malloc(sizeof(char) * lengthFile);
- fin.read(fileData, lengthFile);
- sBuffers[numberOfSocket].outBuf = fileData;
- sBuffers[numberOfSocket].outBufPos = 0;
- sBuffers[numberOfSocket].outBufLength = lengthFile;
- sendto(sd, &lengthFile, sizeof(size_t), 0, (struct sockaddr *)&clientAddresses[numberOfSocket], sizeof(clientAddresses[numberOfSocket]));
- }
- fin.close();
- isSatisfied = true;
- }
- if (!isSatisfied)
- {
- std::string wrongCommandString = WRONG_COMMAND_MESSAGE;
- sendto(sd, wrongCommandString.data(), wrongCommandString.size(), 0, (struct sockaddr *)&clientAddresses[numberOfSocket], sizeof(clientAddresses[numberOfSocket]));
- }
- }
- void readToBuffer(int numberOfSocket)
- {
- char buffer[BUFFER_SIZE];
- memset(buffer, 0, BUFFER_SIZE);
- int rc = read(fds[numberOfSocket].fd, buffer, BUFFER_SIZE);
- if (rc == 0)
- {
- pollhup = true;
- return;
- }
- std::string bufferString(buffer);
- sBuffers[numberOfSocket - 1].inbuf += bufferString;
- size_t pos = bufferString.find_first_of('\n');
- if (pos != std::string::npos)
- {
- processData(sBuffers[numberOfSocket - 1].inbuf, numberOfSocket);
- sBuffers[numberOfSocket - 1].inbuf.clear();
- }
- }
- void *routine(void *args)
- {
- int num = *((int *)args);
- while (true)
- {
- int count = poll(fds.data() + num, 1, 0);
- if (count > 0)
- {
- switch (fds[num].revents)
- {
- case POLLIN:
- readToBuffer(num);
- break;
- case POLLOUT:
- case POLLRDHUP:
- case POLLERR:
- case POLLHUP:
- std::cout << "asdf" << std::endl;
- break;
- case POLLNVAL:
- case POLLRDNORM:
- case POLLWRBAND:
- break;
- default:
- std::cout << "Aboba" << std::endl;
- break;
- }
- fds[num].revents = 0;
- if (pollhup)
- {
- fds.erase(fds.begin() + num, fds.begin() + num + 1);
- sBuffers.erase(sBuffers.begin() + num - 1, sBuffers.begin() + num);
- pollhup = false;
- return NULL;
- }
- }
- int i = num - 1;
- if (sBuffers[i].outBufPos == -1)
- {
- continue;
- }
- size_t bytesToSend;
- if (sBuffers[i].outBufPos + BUFFER_SIZE >= sBuffers[i].outBufLength)
- {
- bytesToSend = sBuffers[i].outBufLength - sBuffers[i].outBufPos;
- }
- else
- {
- bytesToSend = BUFFER_SIZE;
- }
- send(fds[i + 1].fd, sBuffers[i].outBuf + sBuffers[i].outBufPos, bytesToSend, 0);
- sBuffers[i].outBufPos += bytesToSend;
- if (sBuffers[i].outBufPos == sBuffers[i].outBufLength)
- {
- sBuffers[i].outBufPos = -1;
- sBuffers[i].outBufLength = -1;
- free(sBuffers[i].outBuf);
- }
- }
- return NULL;
- }
- void processEventsASYNC()
- {
- if (fds[0].revents == POLLIN)
- {
- struct sockaddr_in clientAddress;
- memset(&clientAddress, 0, sizeof(clientAddress));
- int clientAddressSize = sizeof(clientAddress);
- int sdClient = accept(sd, (struct sockaddr *)&clientAddress, (socklen_t *)&clientAddressSize);
- if (sdClient < 0)
- {
- std::cout << "Can not accept connection" << std::endl;
- }
- else
- {
- struct pollfd client;
- memset(&client, 0, sizeof(client));
- client.fd = sdClient;
- client.events = POLLIN;
- fds.push_back(client);
- struct buffers bufs;
- bufs.outBufPos = -1;
- bufs.outBufLength = -1;
- sBuffers.push_back(bufs);
- int *num = (int *)malloc(sizeof(int));
- *num = fds.size() - 1;
- pthread_create(&threads[lastThread++], 0, routine, (void *)num);
- }
- }
- }
- void processEvents()
- {
- if (fds[0].revents == POLLIN)
- {
- struct sockaddr_in clientAddress;
- memset(&clientAddress, 0, sizeof(clientAddress));
- int clientAddressSize = sizeof(clientAddress);
- int sdClient = accept(sd, (struct sockaddr *)&clientAddress, (socklen_t *)&clientAddressSize);
- if (sdClient < 0)
- {
- std::cout << "Can not accept connection" << std::endl;
- }
- else
- {
- struct pollfd client;
- memset(&client, 0, sizeof(client));
- client.fd = sdClient;
- client.events = POLLIN;
- fds.push_back(client);
- struct buffers bufs;
- bufs.outBufPos = -1;
- bufs.outBufLength = -1;
- sBuffers.push_back(bufs);
- }
- }
- for (int i = 1; i < fds.size(); i++)
- {
- switch (fds[i].revents)
- {
- case POLLIN:
- readToBuffer(i);
- break;
- case POLLOUT:
- case POLLRDHUP:
- case POLLERR:
- case POLLHUP:
- std::cout << "asdf" << std::endl;
- break;
- case POLLNVAL:
- case POLLRDNORM:
- case POLLWRBAND:
- break;
- default:
- std::cout << "Aboba" << std::endl;
- break;
- }
- fds[i].revents = 0;
- if (pollhup)
- {
- fds.erase(fds.begin() + i, fds.begin() + i + 1);
- sBuffers.erase(sBuffers.begin() + i - 1, sBuffers.begin() + i);
- i--;
- pollhup = false;
- }
- }
- }
- void *routineUDP(void *args)
- {
- int num = *((int *)args);
- while (true)
- {
- size_t pos = sBuffers[num].inbuf.find_first_of('\n');
- if (pos != std::string::npos)
- {
- if (sBuffers[num].inbuf == QUIT_MESSAGE)
- {
- clientAddresses.erase(clientAddresses.begin() + num, clientAddresses.begin() + num + 1);
- sBuffers.erase(sBuffers.begin() + num, sBuffers.begin() + num + 1);
- return NULL;
- }
- processDataUDP(sBuffers[num].inbuf, num);
- sBuffers[num].inbuf.clear();
- }
- int i = num;
- if (sBuffers[i].outBufPos == -1)
- {
- continue;
- }
- size_t bytesToSend;
- if (sBuffers[i].outBufPos + BUFFER_SIZE >= sBuffers[i].outBufLength)
- {
- bytesToSend = sBuffers[i].outBufLength - sBuffers[i].outBufPos;
- }
- else
- {
- bytesToSend = BUFFER_SIZE;
- }
- sendto(sd, sBuffers[i].outBuf + sBuffers[i].outBufPos, bytesToSend, 0, (struct sockaddr *)&clientAddresses[i], sizeof(clientAddresses[i]));
- sBuffers[i].outBufPos += bytesToSend;
- if (sBuffers[i].outBufPos == sBuffers[i].outBufLength)
- {
- sBuffers[i].outBufPos = -1;
- sBuffers[i].outBufLength = -1;
- free(sBuffers[i].outBuf);
- }
- }
- return NULL;
- }
- void putClientAddressAndMessageASYNC(struct sockaddr_in address, std::string message)
- {
- bool found = false;
- for (int i = 0; i < clientAddresses.size(); i++)
- {
- char storingAddress[256];
- char incomingAddress[256];
- inet_ntop(AF_INET, &(address.sin_addr), incomingAddress, 256);
- inet_ntop(AF_INET, &(clientAddresses[i].sin_addr), storingAddress, 256);
- if (strcmp(storingAddress, incomingAddress) == 0)
- {
- found = true;
- sBuffers[i].inbuf += message;
- break;
- }
- }
- if (!found)
- {
- clientAddresses.push_back(address);
- struct buffers b;
- b.outBufLength = -1;
- b.outBufPos = -1;
- sBuffers.push_back(b);
- sBuffers[sBuffers.size() - 1].inbuf += message;
- int *num = (int *)malloc(sizeof(int));
- *num = clientAddresses.size() - 1;
- pthread_create(&threads[lastThread++], 0, routineUDP, (void *)num);
- }
- }
- void putClientAddressAndMessage(struct sockaddr_in address, std::string message)
- {
- bool found = false;
- if (message == QUIT_MESSAGE)
- {
- found = true;
- }
- for (int i = 0; i < clientAddresses.size(); i++)
- {
- char storingAddress[256];
- char incomingAddress[256];
- inet_ntop(AF_INET, &(address.sin_addr), incomingAddress, 256);
- inet_ntop(AF_INET, &(clientAddresses[i].sin_addr), storingAddress, 256);
- if (message == QUIT_MESSAGE)
- {
- found = true;
- }
- if (strcmp(storingAddress, incomingAddress) == 0)
- {
- if (message == QUIT_MESSAGE)
- {
- clientAddresses.erase(clientAddresses.begin() + i, clientAddresses.begin() + i + 1);
- sBuffers.erase(sBuffers.begin() + i, sBuffers.begin() + i + 1);
- }
- else
- {
- found = true;
- sBuffers[i].inbuf += message;
- size_t pos = sBuffers[i].inbuf.find_first_of('\n');
- if (pos != std::string::npos)
- {
- processDataUDP(sBuffers[i].inbuf, i);
- sBuffers[i].inbuf.clear();
- }
- }
- break;
- }
- }
- if (!found)
- {
- clientAddresses.push_back(address);
- struct buffers b;
- b.outBufLength = -1;
- b.outBufPos = -1;
- sBuffers.push_back(b);
- sBuffers[sBuffers.size() - 1].inbuf += message;
- size_t pos = sBuffers[sBuffers.size() - 1].inbuf.find_first_of('\n');
- if (pos != std::string::npos)
- {
- processDataUDP(sBuffers[sBuffers.size() - 1].inbuf, sBuffers.size() - 1);
- sBuffers[sBuffers.size() - 1].inbuf.clear();
- }
- }
- }
- void processEventsUDPASYNC()
- {
- if (fds[0].revents == POLLIN)
- {
- struct sockaddr_in clientAddress;
- memset(&clientAddress, 0, sizeof(clientAddress));
- int clientAddressSize = sizeof(clientAddress);
- char messBuf[256];
- memset(messBuf, 0, 256);
- recvfrom(sd, messBuf, 256, 0, (struct sockaddr *)&clientAddress, (socklen_t *)&clientAddressSize);
- std::string data(messBuf);
- if (data == "")
- {
- data.clear();
- data = QUIT_MESSAGE + '\n';
- }
- putClientAddressAndMessageASYNC(clientAddress, data);
- }
- }
- void processEventsUDP()
- {
- if (fds[0].revents == POLLIN)
- {
- struct sockaddr_in clientAddress;
- memset(&clientAddress, 0, sizeof(clientAddress));
- int clientAddressSize = sizeof(clientAddress);
- char messBuf[256];
- memset(messBuf, 0, 256);
- recvfrom(sd, messBuf, 256, 0, (struct sockaddr *)&clientAddress, (socklen_t *)&clientAddressSize);
- std::string data(messBuf);
- putClientAddressAndMessage(clientAddress, data);
- }
- }
- void processSend()
- {
- for (int i = 0; i < sBuffers.size(); i++)
- {
- if (sBuffers[i].outBufPos == -1)
- {
- continue;
- }
- size_t bytesToSend;
- if (sBuffers[i].outBufPos + BUFFER_SIZE >= sBuffers[i].outBufLength)
- {
- bytesToSend = sBuffers[i].outBufLength - sBuffers[i].outBufPos;
- }
- else
- {
- bytesToSend = BUFFER_SIZE;
- }
- send(fds[i + 1].fd, sBuffers[i].outBuf + sBuffers[i].outBufPos, bytesToSend, 0);
- sBuffers[i].outBufPos += bytesToSend;
- if (sBuffers[i].outBufPos == sBuffers[i].outBufLength)
- {
- sBuffers[i].outBufPos = -1;
- sBuffers[i].outBufLength = -1;
- free(sBuffers[i].outBuf);
- }
- }
- }
- void processSendUDP()
- {
- for (int i = 0; i < sBuffers.size(); i++)
- {
- if (sBuffers[i].outBufPos == -1)
- {
- continue;
- }
- size_t bytesToSend;
- if (sBuffers[i].outBufPos + BUFFER_SIZE >= sBuffers[i].outBufLength)
- {
- bytesToSend = sBuffers[i].outBufLength - sBuffers[i].outBufPos;
- }
- else
- {
- bytesToSend = BUFFER_SIZE;
- }
- sendto(sd, sBuffers[i].outBuf + sBuffers[i].outBufPos, bytesToSend, 0, (struct sockaddr *)&clientAddresses[i], sizeof(clientAddresses[i]));
- sBuffers[i].outBufPos += bytesToSend;
- if (sBuffers[i].outBufPos == sBuffers[i].outBufLength)
- {
- sBuffers[i].outBufPos = -1;
- sBuffers[i].outBufLength = -1;
- free(sBuffers[i].outBuf);
- }
- }
- }
- void startPollingUDPASYNC()
- {
- while (true)
- {
- int numberOfEvents = poll(fds.data(), fds.size(), 0);
- if (numberOfEvents < 0)
- {
- std::cout << "ERROR!" << std::endl;
- exit(-1);
- }
- if (numberOfEvents > 0)
- {
- processEventsUDPASYNC();
- }
- }
- }
- void startPollingUDP()
- {
- while (true)
- {
- int numberOfEvents = poll(fds.data(), fds.size(), 0);
- if (numberOfEvents < 0)
- {
- std::cout << "ERROR!" << std::endl;
- exit(-1);
- }
- if (numberOfEvents > 0)
- {
- processEventsUDP();
- }
- processSendUDP();
- }
- }
- void startPollingASYNC()
- {
- while (true)
- {
- int numberOfEvents = poll(fds.data(), 1, 0);
- if (numberOfEvents < 0)
- {
- std::cout << "ERROR!" << std::endl;
- exit(-1);
- }
- if (numberOfEvents > 0)
- {
- processEventsASYNC();
- }
- }
- }
- void startPolling()
- {
- while (true)
- {
- int numberOfEvents = poll(fds.data(), fds.size(), 0);
- if (numberOfEvents < 0)
- {
- std::cout << "ERROR!" << std::endl;
- exit(-1);
- }
- if (numberOfEvents > 0)
- {
- processEvents();
- }
- processSend();
- }
- }
- int main()
- {
- configureServer();
- int choice;
- std::cout << "Choose mode:" << std::endl;
- std::cout << "1. Sync\n2. Async\n";
- std::cin >> choice;
- switch (choice)
- {
- case 1:
- if (SOCKET_TYPE == SOCK_STREAM)
- {
- startPolling();
- }
- else
- {
- startPollingUDP();
- }
- break;
- case 2:
- if (SOCKET_TYPE == SOCK_STREAM)
- {
- startPollingASYNC();
- }
- else
- {
- startPollingUDPASYNC();
- }
- break;
- default:
- std::cout << "Wrong choice" << std::endl;
- }
- close(sd);
- }
Advertisement
Add Comment
Please, Sign In to add comment