... #include "cFile.h" #include <iostream> static const std::string DEF_INPUT_PATH = "../../data/input"; static const std::string DEF_OUTPUT_PATH = "../../data/output"; static const std::string DEF_INPUT_IMAGE_FILE = "../../data/input/cpp.png"; static const std::string DEF_INPUT_CV_FILE = "../../data/input/cv.txt"; static const std::string DEF_INPUT_NO_IMAGE_FILE = "../../data/input/no-file.img"; static const std::string DEF_INPUT_NO_PATH = "../../data/input/no-path"; static const std::string DEF_OUTPUT_NEW_PATH = "../../data/output/new/path"; static const std::string DEF_OUTPUT_IMAGE_FILE = "../../data/output/image/cpp.png"; static const std::string DEF_OUTPUT_CV_FILE = "../../data/output/text/cv.txt"; int main(int, char **) { { cFile oFile(DEF_INPUT_IMAGE_FILE); std::cout << DEF_INPUT_IMAGE_FILE << std::endl << "|oFile.exitsFile()=" << oFile.exitsFile() << std::endl << "|oFile.isFile()=" << oFile.isFile() << std::endl << "|oFile.isDir()=" << oFile.isDir() << std::endl << "|oFile.getFilename()=" << oFile.getFilename() << std::endl << "|oFile.getBasename()=" << oFile.getBasename() << std::endl << "|oFile.getExtension()=" << oFile.getExtension() << std::endl << "|oFile.getPath()=" << oFile.getPath() << std::endl << "|oFile.getAbsolutePath()=" << oFile.getAbsolutePath() << std::endl << std::endl; } { cFile oFile(DEF_INPUT_NO_IMAGE_FILE); std::cout << DEF_INPUT_NO_IMAGE_FILE << std::endl << "|oFile.exitsFile()=" << oFile.exitsFile() << std::endl << "|oFile.isFile()=" << oFile.isFile() << std::endl << "|oFile.isDir()=" << oFile.isDir() << std::endl << "|oFile.getFilename()=" << oFile.getFilename() << std::endl << "|oFile.getBasename()=" << oFile.getBasename() << std::endl << "|oFile.getExtension()=" << oFile.getExtension() << std::endl << "|oFile.getPath()=" << oFile.getPath() << std::endl << "|oFile.getAbsolutePath()=" << oFile.getAbsolutePath() << std::endl << std::endl; } { cFile oFile(DEF_INPUT_PATH); std::cout << DEF_INPUT_PATH << std::endl << "|oFile.exitsFile()=" << oFile.exitsFile() << std::endl << "|oFile.isFile()=" << oFile.isFile() << std::endl << "|oFile.isDir()=" << oFile.isDir() << std::endl << "|oFile.getFilename()=" << oFile.getFilename() << std::endl << "|oFile.getBasename()=" << oFile.getBasename() << std::endl << "|oFile.getExtension()=" << oFile.getExtension() << std::endl << "|oFile.getPath()=" << oFile.getPath() << std::endl << "|oFile.getAbsolutePath()=" << oFile.getAbsolutePath() << std::endl << std::endl; } { cFile oFile(DEF_INPUT_NO_PATH); std::cout << DEF_INPUT_NO_PATH << std::endl << "|oFile.exitsFile()=" << oFile.exitsFile() << std::endl << "|oFile.isFile()=" << oFile.isFile() << std::endl << "|oFile.isDir()=" << oFile.isDir() << std::endl << "|oFile.getFilename()=" << oFile.getFilename() << std::endl << "|oFile.getBasename()=" << oFile.getBasename() << std::endl << "|oFile.getExtension()=" << oFile.getExtension() << std::endl << "|oFile.getPath()=" << oFile.getPath() << std::endl << "|oFile.getAbsolutePath()=" << oFile.getAbsolutePath() << std::endl << std::endl; } { cFile oFile(DEF_OUTPUT_NEW_PATH); std::cout << DEF_OUTPUT_NEW_PATH << std::endl << "|oFile.createDirectory()=" << oFile.createDirectory() << std::endl << std::endl; oFile.createDirectory(); } { cFile oInput(DEF_INPUT_CV_FILE); std::string oCV = oInput.readText(); cFile oOutput(DEF_OUTPUT_CV_FILE); if (cFile(oOutput.getPath()).createDirectory()) { oOutput.writeText(oCV); } std::cout << DEF_INPUT_CV_FILE << std::endl << DEF_OUTPUT_CV_FILE << std::endl << "|oInput.readText()=" << "readText" << std::endl << "|oOutput.writeText()=" << "writeBin" << std::endl << "|oCV.length()=" << oCV.length() << std::endl << "|oCV.size()=" << oCV.size() << std::endl << std::endl; } { cFile oInput(DEF_INPUT_IMAGE_FILE); std::string oImage = oInput.readBin(); cFile oOutput(DEF_OUTPUT_IMAGE_FILE); if (cFile(oOutput.getPath()).createDirectory()) { oOutput.writeBin(oImage); } std::cout << DEF_INPUT_IMAGE_FILE << std::endl << DEF_OUTPUT_IMAGE_FILE << std::endl << "|oInput.readBin()=" << "readBin" << std::endl << "|oOutput.writeBin()=" << "writeBin" << std::endl << "|oImage.length()=" << oImage.length() << std::endl << "|oImage.size()=" << oImage.size() << std::endl << std::endl; } } ...
... #pragma once #include <string> class cFile { public: explicit cFile(const std::string &_filename); ~cFile(); bool exitsFile() const; bool isFile() const; bool isDir() const; std::string getFilename() const; std::string getBasename() const; std::string getExtension() const; std::string getPath() const; std::string getAbsolutePath() const; bool createDirectory() const; std::string readText() const; void writeText(const std::string &_data) const; std::string readBin() const; void writeBin(const std::string &_data) const; private: std::string m_filename; }; ...
... #include "cFile.h" #include <fstream> #include <sstream> #include <filesystem> #include <vector> cFile::cFile(const std::string &_filename) : m_filename(_filename) { } cFile::~cFile() { } bool cFile::exitsFile() const { std::ifstream oFile(m_filename); return oFile.good(); } bool cFile::isFile() const { std::filesystem::path oPath(m_filename); return std::filesystem::is_regular_file(oPath); } bool cFile::isDir() const { std::filesystem::path oPath(m_filename); return std::filesystem::is_directory(oPath); } std::string cFile::getFilename() const { std::filesystem::path oPath(m_filename); return oPath.filename().string(); } std::string cFile::getBasename() const { std::filesystem::path oPath(m_filename); return oPath.stem().string(); } std::string cFile::getExtension() const { std::filesystem::path oPath(m_filename); return oPath.extension().string(); } std::string cFile::getPath() const { std::filesystem::path oPath(m_filename); return oPath.parent_path().string(); } std::string cFile::getAbsolutePath() const { try { std::filesystem::path oPath(m_filename); return std::filesystem::canonical(oPath).string(); } catch (...) { } return ""; } bool cFile::createDirectory() const { try { std::filesystem::create_directories(m_filename); return true; } catch (...) { } return false; } std::string cFile::readText() const { std::ifstream oFile(m_filename); std::stringstream oBuffer; oBuffer << oFile.rdbuf(); return oBuffer.str(); } void cFile::writeText(const std::string &_data) const { std::ofstream oFile(m_filename); oFile << _data.c_str(); } std::string cFile::readBin() const { std::ifstream oFile(m_filename, std::ios::in | std::ios::binary); std::vector<char> oData = std::vector<char>(std::istreambuf_iterator<char>(oFile), std::istreambuf_iterator<char>()); return std::string(&oData[0], oData.size()); } void cFile::writeBin(const std::string &_data) const { std::ofstream oFile(m_filename, std::ios::out | std::ios::binary); oFile.write(&_data[0], _data.size()); } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) add_executable(${PROJECT_NAME} main.cpp cFile.cpp ) ...
... rdvcpp.exe ...
... #include "cServer.h" int main(int _argc, char **_argv) { cServer oServer(_argc, _argv); oServer.run(); return 0; } ...
... #pragma once #include <string> class cServer { public: explicit cServer(int _argc, char **_argv); ~cServer(); void run(); private: std::string getLastError(int _error) const; private: int m_argc; char **m_argv; }; ...
... #include "cServer.h" #include "cServerInit.h" #include <winsock2.h> #include <iostream> static const int DEF_WINSOCK_MAJOR_VERSION = 2; static const int DEF_WINSOCK_MINOR_VERSION = 2; static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; cServer::cServer(int _argc, char **_argv) : m_argc(_argc), m_argv(_argv) { } cServer::~cServer() { } void cServer::run() { WSADATA oWSADATA; int oWSAStartup = WSAStartup(MAKEWORD(DEF_WINSOCK_MAJOR_VERSION, DEF_WINSOCK_MINOR_VERSION), &oWSADATA); if (oWSAStartup != 0) { std::cout << "L'initialisation du point de terminaison a echoue." << "|errorCode=" << oWSAStartup << "|errorMsg=" << getLastError(oWSAStartup) << "|WINSOCK_MAJOR_VERSION=" << DEF_WINSOCK_MAJOR_VERSION << "|WINSOCK_MINOR_VERSION=" << DEF_WINSOCK_MINOR_VERSION << std::endl; return; } cServerInit oServerRun; oServerRun.run(); } std::string cServer::getLastError(int _error) const { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, sizeof(oErrorMsg), NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... #pragma once #include <string> class cServerInit { friend class cServer; private: explicit cServerInit(); ~cServerInit(); void run(); private: std::string getLastError(int _error) const; }; ...
... #include "cServerInit.h" #include "cServerSocket.h" #include <winsock2.h> #include <iostream> static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; cServerInit::cServerInit() { } cServerInit::~cServerInit() { WSACleanup(); } void cServerInit::run() { SOCKET oSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (oSocket == INVALID_SOCKET) { std::cout << "La creation du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; return; } cServerSocket oServerSocket(oSocket); oServerSocket.run(); } std::string cServerInit::getLastError(int _error) const { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, sizeof(oErrorMsg), NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... #pragma once #include <string> #include <winsock2.h> class cServerSocket { friend class cServerInit; private: explicit cServerSocket(SOCKET _socket); ~cServerSocket(); void run(); private: static void onAccept(SOCKET _client); std::string getLastError(int _error) const; private: SOCKET m_socket; }; ...
... #include "cServerSocket.h" #include "cServerClient.h" #include <future> #include <iostream> static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; static const int DEF_WINSOCK_SERVER_PORT = 5555; static const int DEF_WINSOCK_SERVER_BACKLOG = 10; cServerSocket::cServerSocket(SOCKET _socket) : m_socket(_socket) { } cServerSocket::~cServerSocket() { closesocket(m_socket); } void cServerSocket::run() { SOCKADDR_IN oServerAddr; oServerAddr.sin_addr.s_addr = INADDR_ANY; oServerAddr.sin_family = AF_INET; oServerAddr.sin_port = htons(DEF_WINSOCK_SERVER_PORT); if ((bind(m_socket, reinterpret_cast<SOCKADDR *>(&oServerAddr), sizeof(oServerAddr))) == SOCKET_ERROR) { std::cout << "La liaison de l'adresse du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; return; } if ((listen(m_socket, DEF_WINSOCK_SERVER_BACKLOG)) == SOCKET_ERROR) { std::cout << "L'initialisation du nombre de connexions au point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; return; } std::cout << "Le serveur a demarre..." << "|port=" << DEF_WINSOCK_SERVER_PORT << std::endl; while (true) { SOCKADDR_IN oAddress; int oSize = sizeof(oAddress); SOCKET oClient = accept(m_socket, reinterpret_cast<SOCKADDR *>(&oAddress), &oSize); if (oClient == INVALID_SOCKET) { std::cout << "La connexion d'un client au point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; continue; } auto fut = std::async(std::launch::async, onAccept, oClient); } } void cServerSocket::onAccept(SOCKET _client) { cServerClient oServerClient(_client); oServerClient.run(); } std::string cServerSocket::getLastError(int _error) const { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, sizeof(oErrorMsg), NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... #pragma once #include <string> #include <winsock2.h> class cServerClient { friend class cServerSocket; private: explicit cServerClient(SOCKET _socket); ~cServerClient(); void run(); private: bool recvData(std::string &_request); bool sendData(const std::string &_response); std::string getLastError(int _error) const; private: SOCKET m_socket; }; ...
... #include "cServerClient.h" #include <iostream> static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; static const int DEF_WINSOCK_BUFFER_SIZE = 1024; cServerClient::cServerClient(SOCKET _socket) : m_socket(_socket) { } cServerClient::~cServerClient() { closesocket(m_socket); } void cServerClient::run() { std::string oRequest; std::string oResponse = "Un probleme a ete rencontre."; if (recvData(oRequest)) { oResponse = "Votre requete a ete traite avec succes."; } sendData(oResponse); std::cout << "[Client] : " << oRequest << std::endl; std::cout << "[Server] : " << oResponse << std::endl; } bool cServerClient::recvData(std::string &_request) { char oBuffer[DEF_WINSOCK_BUFFER_SIZE]; int oBytes = recv(m_socket, oBuffer, DEF_WINSOCK_BUFFER_SIZE, 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; return false; } oBuffer[oBytes] = '\0'; _request = oBuffer; return true; } bool cServerClient::sendData(const std::string &_response) { int oBytes = send(m_socket, _response.c_str(), (int)_response.length(), 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; return false; } return true; } std::string cServerClient::getLastError(int _error) const { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, sizeof(oErrorMsg), NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) add_executable(${PROJECT_NAME} main.cpp cServer.cpp cServerInit.cpp cServerSocket.cpp cServerClient.cpp ) target_link_libraries(${PROJECT_NAME} ws2_32 ) ...
... rdvcpp.exe ...
... #include "cClient.h" #include <iostream> int main(int _argc, char **_argv) { cClient oClient(_argc, _argv); std::string oRequest("Bonjour tout le monde"); std::string oResponse; if (oClient.run(oRequest, oResponse)) { std::cout << "[Client] : " << oRequest << std::endl; std::cout << "[Server] : " << oResponse << std::endl; } return 0; } ...
... #pragma once #include <string> class cClient { public: explicit cClient(int _argc, char **_argv); ~cClient(); bool run(const std::string &_request, std::string &_response) const; private: std::string getLastError(int _error) const; private: int m_argc; char **m_argv; }; ...
... #include "cClient.h" #include "cClientInit.h" #include <winsock2.h> #include <iostream> static const int DEF_WINSOCK_MAJOR_VERSION = 2; static const int DEF_WINSOCK_MINOR_VERSION = 2; static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; cClient::cClient(int _argc, char **_argv) : m_argc(_argc), m_argv(_argv) { } cClient::~cClient() { } bool cClient::run(const std::string &_request, std::string &_response) const { WSADATA oWSADATA; int oWSAStartup = WSAStartup(MAKEWORD(DEF_WINSOCK_MAJOR_VERSION, DEF_WINSOCK_MINOR_VERSION), &oWSADATA); if (oWSAStartup != 0) { std::cout << "L'initialisation du point de terminaison a echoue." << "|errorCode=" << oWSAStartup << "|errorMsg=" << getLastError(oWSAStartup) << "|WINSOCK_MAJOR_VERSION=" << DEF_WINSOCK_MAJOR_VERSION << "|WINSOCK_MINOR_VERSION=" << DEF_WINSOCK_MINOR_VERSION << std::endl; return false; } cClientInit oClientRun; return oClientRun.run(_request, _response); } std::string cClient::getLastError(int _error) const { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, sizeof(oErrorMsg), NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... #pragma once #include <string> class cClientInit { friend class cClient; private: explicit cClientInit(); ~cClientInit(); bool run(const std::string &_request, std::string &_response) const; private: std::string getLastError(int _error) const; }; ...
... #include "cClientInit.h" #include "cClientSocket.h" #include <winsock2.h> #include <iostream> static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; cClientInit::cClientInit() { } cClientInit::~cClientInit() { WSACleanup(); } bool cClientInit::run(const std::string &_request, std::string &_response) const { SOCKET oSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (oSocket == INVALID_SOCKET) { std::cout << "La creation du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; return false; } cClientSocket oClientSocket(oSocket); return oClientSocket.run(_request, _response); } std::string cClientInit::getLastError(int _error) const { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, sizeof(oErrorMsg), NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... #pragma once #include <string> #include <winsock2.h> class cClientSocket { friend class cClientInit; private: explicit cClientSocket(SOCKET _socket); ~cClientSocket(); bool run(const std::string &_request, std::string &_response); private: bool recvData(std::string &_response); bool sendData(const std::string &_request); std::string getLastError(int _error) const; private: SOCKET m_socket; }; ...
... #include "cClientSocket.h" #include <ws2tcpip.h> #include <iostream> static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; static const char *DEF_WINSOCK_SERVER_ADDRESS = "127.0.0.1"; static const int DEF_WINSOCK_SERVER_PORT = 5555; static const int DEF_WINSOCK_BUFFER_SIZE = 1024; cClientSocket::cClientSocket(SOCKET _socket) : m_socket(_socket) { } cClientSocket::~cClientSocket() { closesocket(m_socket); } bool cClientSocket::run(const std::string &_request, std::string &_response) { SOCKADDR_IN oServerAddress; InetPton(AF_INET, DEF_WINSOCK_SERVER_ADDRESS, &oServerAddress.sin_addr.s_addr); oServerAddress.sin_family = AF_INET; oServerAddress.sin_port = htons(DEF_WINSOCK_SERVER_PORT); if (connect(m_socket, reinterpret_cast<SOCKADDR *>(&oServerAddress), sizeof(oServerAddress)) == SOCKET_ERROR) { std::cout << "La connexion au point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; return false; } if (sendData(_request)) { recvData(_response); } return true; } bool cClientSocket::recvData(std::string &_response) { char oBuffer[DEF_WINSOCK_BUFFER_SIZE]; int oBytes = recv(m_socket, oBuffer, DEF_WINSOCK_BUFFER_SIZE, 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; return false; } oBuffer[oBytes] = '\0'; _response = oBuffer; return true; } bool cClientSocket::sendData(const std::string &_request) { int oBytes = send(m_socket, _request.c_str(), (int)_request.length(), 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastError(GetLastError()) << std::endl; return false; } return true; } std::string cClientSocket::getLastError(int _error) const { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, sizeof(oErrorMsg), NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) add_executable(rdvcpp main.cpp cClient.cpp cClientInit.cpp cClientSocket.cpp ) target_link_libraries(${PROJECT_NAME} ws2_32 ) ...
... rdvcpp.exe ...
... #include "cServer.h" int main(int _argc, char **_argv) { cServer oServer; oServer.run(); return 0; } ...
... #pragma once #include <string> class cServer { public: explicit cServer(); ~cServer(); void run(); }; ...
... #include "cServer.h" #include "cServerInit.h" #include "cErrorMsg.h" #include <winsock2.h> #include <iostream> // winsock2 static const int DEF_WINSOCK_MAJOR_VERSION = 2; static const int DEF_WINSOCK_MINOR_VERSION = 2; cServer::cServer() { } cServer::~cServer() { } void cServer::run() { WSADATA oWSADATA; int oWSAStartup = WSAStartup(MAKEWORD(DEF_WINSOCK_MAJOR_VERSION, DEF_WINSOCK_MINOR_VERSION), &oWSADATA); if (oWSAStartup != 0) { std::cout << "L'initialisation du point de terminaison a echoue." << "|errorCode=" << oWSAStartup << "|errorMsg=" << getLastErrorMsg(oWSAStartup) << "|WINSOCK_MAJOR_VERSION=" << DEF_WINSOCK_MAJOR_VERSION << "|WINSOCK_MINOR_VERSION=" << DEF_WINSOCK_MINOR_VERSION << std::endl; return; } cServerInit oServerRun; oServerRun.run(); } ...
... #pragma once #include <string> class cServerInit { friend class cServer; private: explicit cServerInit(); ~cServerInit(); void run(); }; ...
... #include "cServerInit.h" #include "cServerSocket.h" #include "cErrorMsg.h" #include <winsock2.h> #include <iostream> cServerInit::cServerInit() { } cServerInit::~cServerInit() { WSACleanup(); } void cServerInit::run() { SOCKET oSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (oSocket == INVALID_SOCKET) { std::cout << "La creation du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return; } cServerSocket oServerSocket(oSocket); oServerSocket.run(); } ...
... #pragma once #include <string> #include <winsock2.h> class cServerSocket { friend class cServerInit; private: explicit cServerSocket(SOCKET _socket); ~cServerSocket(); void run(); private: static void onAccept(SOCKET _client); private: SOCKET m_socket; }; ...
... #include "cServerSocket.h" #include "cServerClient.h" #include "cErrorMsg.h" #include <future> #include <iostream> // winsock2 static const int DEF_WINSOCK_SERVER_PORT = 5555; static const int DEF_WINSOCK_SERVER_BACKLOG = 10; cServerSocket::cServerSocket(SOCKET _socket) : m_socket(_socket) { } cServerSocket::~cServerSocket() { closesocket(m_socket); } void cServerSocket::run() { SOCKADDR_IN oServerAddr; oServerAddr.sin_addr.s_addr = INADDR_ANY; oServerAddr.sin_family = AF_INET; oServerAddr.sin_port = htons(DEF_WINSOCK_SERVER_PORT); if ((bind(m_socket, reinterpret_cast<SOCKADDR *>(&oServerAddr), sizeof(oServerAddr))) == SOCKET_ERROR) { std::cout << "La liaison de l'adresse du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return; } if ((listen(m_socket, DEF_WINSOCK_SERVER_BACKLOG)) == SOCKET_ERROR) { std::cout << "L'initialisation du nombre de connexions au point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return; } std::cout << "Le serveur a demarre..." << "|port=" << DEF_WINSOCK_SERVER_PORT << std::endl; while (true) { SOCKADDR_IN oAddress; int oSize = sizeof(oAddress); SOCKET oClient = accept(m_socket, reinterpret_cast<SOCKADDR *>(&oAddress), &oSize); if (oClient == INVALID_SOCKET) { std::cout << "La connexion d'un client au point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; continue; } auto oFuture = std::async(std::launch::async, onAccept, oClient); } } void cServerSocket::onAccept(SOCKET _client) { cServerClient oServerClient(_client); oServerClient.run(); } ...
... #pragma once #include <string> #include <winsock2.h> class cServerClient { friend class cServerSocket; private: explicit cServerClient(SOCKET _socket); ~cServerClient(); void run(); private: bool recvData(std::string &_request); bool sendData(const std::string &_response); private: SOCKET m_socket; }; ...
... #include "cServerClient.h" #include "cFTP.h" #include "cString.h" #include "cErrorMsg.h" #include <iostream> // winsock2 static const int DEF_WINSOCK_BUFFER_SIZE = 1024; static const int DEF_WINSOCK_BUFFER_MAX = 1 * 1024 * 1024; // 1 Mo // limit static const int DEF_REQUEST_LIMIT_SIZE = 100; cServerClient::cServerClient(SOCKET _socket) : m_socket(_socket) { } cServerClient::~cServerClient() { closesocket(m_socket); } void cServerClient::run() { std::string oRequest; std::string oResponse; cFTP::sFTP aFTP; if (recvData(oRequest)) { cFTP oFTP; if (oFTP.saveFile(oRequest, aFTP)) { oResponse = "Votre requete a ete traite avec succes."; } else { oResponse = "Le chargement du fichier a echoue."; } } else { oResponse = "Un probleme a ete rencontre."; } sendData(oResponse); std::cout << "[Client] : ================================" << std::endl; std::cout << "[Client] : sFTP.path=" << aFTP.path << std::endl; std::cout << "[Client] : sFTP.filename=" << aFTP.filename << std::endl; std::cout << "[Client] : sFTP.size=" << aFTP.size << std::endl; std::cout << "[Client] : sFTP.data.size()=" << aFTP.data.size() << std::endl; std::cout << "[Client] : sFTP.data=" << cString(aFTP.data).limit(DEF_REQUEST_LIMIT_SIZE).oneLine() << std::endl; std::cout << "[Server] : " << oResponse << std::endl; } bool cServerClient::recvData(std::string &_request) { std::string oRequest; char oBuffer[DEF_WINSOCK_BUFFER_SIZE]; while (true) { int oBytes = recv(m_socket, oBuffer, DEF_WINSOCK_BUFFER_SIZE - 1, 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } oRequest.append(oBuffer, oBytes); if (oRequest.size() >= DEF_WINSOCK_BUFFER_MAX) { std::cout << "Le nombre maximal de donnees sur le point de terminaison a ete atteint." << "|DEF_WINSOCK_BUFFER_MAX=" << DEF_WINSOCK_BUFFER_MAX << std::endl; return false; } u_long oBytesIO; int isOK = ioctlsocket(m_socket, FIONREAD, &oBytesIO); if (isOK == SOCKET_ERROR) { std::cout << "La lecture du nombre de donnees restantes sur le point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } if (oBytesIO == 0) { break; } } _request = oRequest; return true; } bool cServerClient::sendData(const std::string &_response) { int oBytes = send(m_socket, _response.c_str(), (int)_response.length(), 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } return true; } ...
... #pragma once #include <string> class cFTP { public: struct sFTP { std::string path; std::string filename; size_t size; std::string data; }; public: explicit cFTP(); ~cFTP(); bool saveFile(const std::string &_request, sFTP &_sFTP); private: bool deserialize(const std::string &_request, sFTP &_sFTP); }; ...
... #include "cFTP.h" #include "cFile.h" #include "cString.h" #include <iostream> // output static const std::string DEF_OUTPUT_PATH = "../../data/output"; // request static const int DEF_REQUEST_LIMIT_SIZE = 100; static const std::string DEF_REQUEST_DATA_SEP = ";"; cFTP::cFTP() { } cFTP::~cFTP() { } bool cFTP::saveFile(const std::string &_request, sFTP &_sFTP) { if (!deserialize(_request, _sFTP)) { std::cout << "La deserialisation des donnees du fichier a echoue." << "|request=" << cString(_request).limit(DEF_REQUEST_LIMIT_SIZE).oneLine() << std::endl; return false; } if (!cFile(DEF_OUTPUT_PATH).createDirectory()) { std::cout << "La creation du fichier de sortie a echoue." << "|request=" << cString(_request).limit(DEF_REQUEST_LIMIT_SIZE).oneLine() << std::endl; return false; } std::string oFilename = DEF_OUTPUT_PATH + "/" + _sFTP.filename; cFile oFile(oFilename); oFile.writeBin(_sFTP.data); return true; } bool cFTP::deserialize(const std::string &_request, sFTP &_sFTP) { // path size_t oPathStart = 0; size_t oPathEnd = _request.find(DEF_REQUEST_DATA_SEP, oPathStart); if (oPathEnd == std::string::npos) { std::cout << "Le chemin du fichier est inconnu." << "|request=" << cString(_request).limit(DEF_REQUEST_LIMIT_SIZE).oneLine() << std::endl; return false; } _sFTP.path = _request.substr(oPathStart, oPathEnd - oPathStart); // filename size_t oFilenameStart = oPathEnd + DEF_REQUEST_DATA_SEP.size(); size_t oFilenameEnd = _request.find(DEF_REQUEST_DATA_SEP, oFilenameStart); if (oFilenameEnd == std::string::npos) { std::cout << "Le nom du fichier est inconnu." << "|request=" << cString(_request).limit(DEF_REQUEST_LIMIT_SIZE).oneLine() << std::endl; return false; } _sFTP.filename = _request.substr(oFilenameStart, oFilenameEnd - oFilenameStart); // size size_t oSizeStart = oFilenameEnd + DEF_REQUEST_DATA_SEP.size(); size_t oSizeEnd = _request.find(DEF_REQUEST_DATA_SEP, oSizeStart); if (oSizeEnd == std::string::npos) { std::cout << "La taille du fichier est inconnu." << "|request=" << cString(_request).limit(DEF_REQUEST_LIMIT_SIZE).oneLine() << std::endl; return false; } std::string oSize = _request.substr(oSizeStart, oSizeEnd - oSizeStart); if (!cString(oSize).toInt(_sFTP.size)) { std::cout << "Le format de la taille du fichier est incorrect." << "|size=" << cString(oSize).limit(DEF_REQUEST_LIMIT_SIZE).oneLine() << std::endl; return false; } // data size_t oDataStart = oSizeEnd + DEF_REQUEST_DATA_SEP.size(); _sFTP.data = _request.substr(oDataStart); return true; } ...
... #pragma once #include <string> std::string getLastErrorMsg(int _error); ...
... #include "cErrorMsg.h" #include <Windows.h> static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; std::string getLastErrorMsg(int _error) { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, DEF_WINSOCK_ERROR_MSG_LENGTH - 1, NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) add_executable(${PROJECT_NAME} main.cpp cServer.cpp cServerInit.cpp cServerSocket.cpp cServerClient.cpp cFile.cpp cFTP.cpp cErrorMsg.cpp cString.cpp ) target_link_libraries(${PROJECT_NAME} ws2_32 ) ...
... rdvcpp.exe ...
... #include "cFTP.h" static const std::string DEF_INPUT_CV_FILE = "../../data/input/cv.txt"; static const std::string DEF_INPUT_IMAGE_FILE = "../../data/input/cpp.png"; int main(int _argc, char **_argv) { cFTP oFTP; oFTP.sendFile(DEF_INPUT_CV_FILE); oFTP.sendFile(DEF_INPUT_IMAGE_FILE); return 0; } ...
... #pragma once #include <string> class cFTP { public: struct sFTP { std::string path; std::string filename; size_t size; std::string data; }; public: explicit cFTP(); ~cFTP(); void sendFile(const std::string &_filename); private: bool loadFile(const std::string &_filename, sFTP &_sFTP); std::string serialize(const sFTP &_sFTP); }; ...
... #include "cFTP.h" #include "cFile.h" #include "cClient.h" #include "cString.h" #include <iostream> // request static const int DEF_REQUEST_LIMIT_SIZE = 100; static const std::string DEF_REQUEST_DATA_SEP = ";"; cFTP::cFTP() { } cFTP::~cFTP() { } void cFTP::sendFile(const std::string &_filename) { sFTP oFTP; std::string oRequest; if (loadFile(_filename, oFTP)) { oRequest = serialize(oFTP); } else { oRequest = "Erreur lors du chargement du fichier"; } cClient oClient; std::string oResponse; if (oClient.run(oRequest, oResponse)) { std::cout << "[Client] : ================================" << std::endl; std::cout << "[Client] : oRequest=" << cString(oRequest).limit(DEF_REQUEST_LIMIT_SIZE).oneLine() << std::endl; std::cout << "[Server] : " << oResponse << std::endl; } } bool cFTP::loadFile(const std::string &_filename, sFTP &_sFTP) { cFile oFile(_filename); if (!oFile.exitsFile()) { std::cout << "Le fichier n'existe pas." << "|filename=" << _filename << std::endl; return false; } _sFTP.path = _filename; _sFTP.filename = oFile.getFilename(); _sFTP.data = oFile.readBin(); _sFTP.size = _sFTP.data.size(); return true; } std::string cFTP::serialize(const sFTP &_sFTP) { std::string oData; oData += _sFTP.path + DEF_REQUEST_DATA_SEP; oData += _sFTP.filename + DEF_REQUEST_DATA_SEP; oData += std::to_string(_sFTP.size) + DEF_REQUEST_DATA_SEP; oData.append(&_sFTP.data[0], _sFTP.size); return oData; } ...
... #pragma once #include <string> class cClient { public: explicit cClient(); ~cClient(); bool run(const std::string &_request, std::string &_response) const; }; ...
... #include "cClient.h" #include "cClientInit.h" #include "cErrorMsg.h" #include <winsock2.h> #include <iostream> // winsock2 static const int DEF_WINSOCK_MAJOR_VERSION = 2; static const int DEF_WINSOCK_MINOR_VERSION = 2; cClient::cClient() { } cClient::~cClient() { } bool cClient::run(const std::string &_request, std::string &_response) const { WSADATA oWSADATA; int oWSAStartup = WSAStartup(MAKEWORD(DEF_WINSOCK_MAJOR_VERSION, DEF_WINSOCK_MINOR_VERSION), &oWSADATA); if (oWSAStartup != 0) { std::cout << "L'initialisation du point de terminaison a echoue." << "|errorCode=" << oWSAStartup << "|errorMsg=" << getLastErrorMsg(oWSAStartup) << "|WINSOCK_MAJOR_VERSION=" << DEF_WINSOCK_MAJOR_VERSION << "|WINSOCK_MINOR_VERSION=" << DEF_WINSOCK_MINOR_VERSION << std::endl; return false; } cClientInit oClientRun; return oClientRun.run(_request, _response); } ...
... #pragma once #include <string> class cClientInit { friend class cClient; private: explicit cClientInit(); ~cClientInit(); bool run(const std::string &_request, std::string &_response) const; }; ...
... #include "cClientInit.h" #include "cClientSocket.h" #include "cErrorMsg.h" #include <winsock2.h> #include <iostream> cClientInit::cClientInit() { } cClientInit::~cClientInit() { WSACleanup(); } bool cClientInit::run(const std::string &_request, std::string &_response) const { SOCKET oSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (oSocket == INVALID_SOCKET) { std::cout << "La creation du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } cClientSocket oClientSocket(oSocket); return oClientSocket.run(_request, _response); } ...
... #pragma once #include <string> #include <winsock2.h> class cClientSocket { friend class cClientInit; private: explicit cClientSocket(SOCKET _socket); ~cClientSocket(); bool run(const std::string &_request, std::string &_response); private: bool recvData(std::string &_response); bool sendData(const std::string &_request); private: SOCKET m_socket; }; ...
... #include "cClientSocket.h" #include "cErrorMsg.h" #include <ws2tcpip.h> #include <iostream> // winsock2 static const char *DEF_WINSOCK_SERVER_ADDRESS = "127.0.0.1"; static const int DEF_WINSOCK_SERVER_PORT = 5555; static const int DEF_WINSOCK_BUFFER_SIZE = 1024; cClientSocket::cClientSocket(SOCKET _socket) : m_socket(_socket) { } cClientSocket::~cClientSocket() { closesocket(m_socket); } bool cClientSocket::run(const std::string &_request, std::string &_response) { SOCKADDR_IN oServerAddress; InetPton(AF_INET, DEF_WINSOCK_SERVER_ADDRESS, &oServerAddress.sin_addr.s_addr); oServerAddress.sin_family = AF_INET; oServerAddress.sin_port = htons(DEF_WINSOCK_SERVER_PORT); if (connect(m_socket, reinterpret_cast<SOCKADDR *>(&oServerAddress), sizeof(oServerAddress)) == SOCKET_ERROR) { std::cout << "La connexion au point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } if (sendData(_request)) { recvData(_response); } return true; } bool cClientSocket::recvData(std::string &_response) { char oBuffer[DEF_WINSOCK_BUFFER_SIZE]; int oBytes = recv(m_socket, oBuffer, DEF_WINSOCK_BUFFER_SIZE - 1, 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } oBuffer[oBytes] = '\0'; _response = oBuffer; return true; } bool cClientSocket::sendData(const std::string &_request) { int oBytes = send(m_socket, &_request[0], (int)_request.length(), 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } return true; } ...
... #pragma once #include <string> std::string getLastErrorMsg(int _error); ...
... #include "cErrorMsg.h" #include <Windows.h> static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; std::string getLastErrorMsg(int _error) { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, DEF_WINSOCK_ERROR_MSG_LENGTH - 1, NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 17) add_executable(rdvcpp main.cpp cClient.cpp cClientInit.cpp cClientSocket.cpp cFile.cpp cFTP.cpp cErrorMsg.cpp ) target_link_libraries(${PROJECT_NAME} ws2_32 ) ...
... rdvcpp.exe ...
... #include "cServer.h" int main(int _argc, char **_argv) { cServer oServer; oServer.run(); return 0; } ...
... #pragma once #include <string> class cServer { public: explicit cServer(); ~cServer(); void run(); }; ...
... #include "cServer.h" #include "cServerInit.h" #include "cErrorMsg.h" #include <winsock2.h> #include <iostream> // winsock2 static const int DEF_WINSOCK_MAJOR_VERSION = 2; static const int DEF_WINSOCK_MINOR_VERSION = 2; cServer::cServer() { } cServer::~cServer() { } void cServer::run() { WSADATA oWSADATA; int oWSAStartup = WSAStartup(MAKEWORD(DEF_WINSOCK_MAJOR_VERSION, DEF_WINSOCK_MINOR_VERSION), &oWSADATA); if (oWSAStartup != 0) { std::cout << "L'initialisation du point de terminaison a echoue." << "|errorCode=" << oWSAStartup << "|errorMsg=" << getLastErrorMsg(oWSAStartup) << "|WINSOCK_MAJOR_VERSION=" << DEF_WINSOCK_MAJOR_VERSION << "|WINSOCK_MINOR_VERSION=" << DEF_WINSOCK_MINOR_VERSION << std::endl; return; } cServerInit oServerRun; oServerRun.run(); } ...
... #pragma once #include <string> class cServerInit { friend class cServer; private: explicit cServerInit(); ~cServerInit(); void run(); }; ...
... #include "cServerInit.h" #include "cServerSocket.h" #include "cErrorMsg.h" #include <winsock2.h> #include <iostream> cServerInit::cServerInit() { } cServerInit::~cServerInit() { WSACleanup(); } void cServerInit::run() { SOCKET oSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (oSocket == INVALID_SOCKET) { std::cout << "La creation du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return; } cServerSocket oServerSocket(oSocket); oServerSocket.run(); } ...
... #pragma once #include <string> #include <winsock2.h> class cServerSocket { friend class cServerInit; private: explicit cServerSocket(SOCKET _socket); ~cServerSocket(); void run(); private: static void onAccept(SOCKET _client); private: SOCKET m_socket; }; ...
... #include "cServerSocket.h" #include "cServerClient.h" #include "cErrorMsg.h" #include <future> #include <iostream> // winsock2 static const int DEF_WINSOCK_SERVER_PORT = 5555; static const int DEF_WINSOCK_SERVER_BACKLOG = 10; cServerSocket::cServerSocket(SOCKET _socket) : m_socket(_socket) { } cServerSocket::~cServerSocket() { closesocket(m_socket); } void cServerSocket::run() { SOCKADDR_IN oServerAddr; oServerAddr.sin_addr.s_addr = INADDR_ANY; oServerAddr.sin_family = AF_INET; oServerAddr.sin_port = htons(DEF_WINSOCK_SERVER_PORT); if ((bind(m_socket, reinterpret_cast<SOCKADDR *>(&oServerAddr), sizeof(oServerAddr))) == SOCKET_ERROR) { std::cout << "La liaison de l'adresse du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return; } if ((listen(m_socket, DEF_WINSOCK_SERVER_BACKLOG)) == SOCKET_ERROR) { std::cout << "L'initialisation du nombre de connexions au point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return; } std::cout << "Le serveur a demarre..." << "|port=" << DEF_WINSOCK_SERVER_PORT << std::endl; while (true) { SOCKADDR_IN oAddress; int oSize = sizeof(oAddress); SOCKET oClient = accept(m_socket, reinterpret_cast<SOCKADDR *>(&oAddress), &oSize); if (oClient == INVALID_SOCKET) { std::cout << "La connexion d'un client au point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; continue; } auto oFuture = std::async(std::launch::async, onAccept, oClient); } } void cServerSocket::onAccept(SOCKET _client) { cServerClient oServerClient(_client); oServerClient.run(); } ...
... #pragma once #include <string> #include <winsock2.h> class cServerClient { friend class cServerSocket; private: explicit cServerClient(SOCKET _socket); ~cServerClient(); void run(); private: bool recvData(std::string &_request); bool sendData(const std::string &_response); private: SOCKET m_socket; }; ...
... #include "cServerClient.h" #include "cServerApp.h" #include "cString.h" #include "cErrorMsg.h" #include <iostream> // winsock2 static const int DEF_WINSOCK_BUFFER_SIZE = 1024; static const int DEF_WINSOCK_BUFFER_MAX = 1 * 1024 * 1024; // 1 Mo // limit static const int DEF_DATA_LIMIT_SIZE = 100; cServerClient::cServerClient(SOCKET _socket) : m_socket(_socket) { } cServerClient::~cServerClient() { closesocket(m_socket); } void cServerClient::run() { std::string oRequest; std::string oResponse; if (recvData(oRequest)) { cServerApp oApp; oApp.run(oRequest, oResponse); } else { oResponse = "Un probleme a ete rencontre."; } sendData(oResponse); std::cout << "[Request ]:" << cString(oRequest).escape(DEF_DATA_LIMIT_SIZE) << std::endl; std::cout << "[Response]:" << cString(oResponse).escape(DEF_DATA_LIMIT_SIZE) << std::endl; } bool cServerClient::recvData(std::string &_request) { std::string oRequest; char oBuffer[DEF_WINSOCK_BUFFER_SIZE]; while (true) { int oBytes = recv(m_socket, oBuffer, DEF_WINSOCK_BUFFER_SIZE - 1, 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } oRequest.append(oBuffer, oBytes); if (oRequest.size() >= DEF_WINSOCK_BUFFER_MAX) { std::cout << "Le nombre maximal de donnees sur le point de terminaison a ete atteint." << "|DEF_WINSOCK_BUFFER_MAX=" << DEF_WINSOCK_BUFFER_MAX << std::endl; return false; } u_long oBytesIO; int isOK = ioctlsocket(m_socket, FIONREAD, &oBytesIO); if (isOK == SOCKET_ERROR) { std::cout << "La lecture du nombre de donnees restantes sur le point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } if (oBytesIO == 0) { break; } } _request = oRequest; return true; } bool cServerClient::sendData(const std::string &_response) { int oBytes = send(m_socket, _response.c_str(), (int)_response.length(), 0); if (oBytes == SOCKET_ERROR) { std::cout << "La reception des donnees du point de terminaison a echoue." << "|errorCode=" << GetLastError() << "|errorMsg=" << getLastErrorMsg(GetLastError()) << std::endl; return false; } return true; } ...
... #pragma once #include <string> class cServerApp { friend class cServerClient; private: explicit cServerApp(); ~cServerApp(); void run(const std::string &_request, std::string &_response); }; ...
... #include "cServerApp.h" #include "cHTTP.h" cServerApp::cServerApp() { } cServerApp::~cServerApp() { } void cServerApp::run(const std::string &_request, std::string &_response) { cHTTP oHTTP; _response = oHTTP.getResponse("<h1>Bonjour tout le monde.</h1>"); } ...
... #pragma once #include <string> class cHTTP { private: struct sResponse { std::string version; int status; std::string reason; std::string connection; std::string contentType; int contentLength; std::string contentText; }; public: cHTTP(); ~cHTTP(); std::string getResponse(const std::string &_content) const; private: sResponse initResponse(const std::string &_content) const; }; ...
... #include "cHTTP.h" #include <format> #include <sstream> static const std::string DEF_HTTP_VERSION_1_1 = "HTTP/1.1"; static const int DEF_HTTP_STATUS_200 = 200; static const std::string DEF_HTTP_REASON_OK = "OK"; static const std::string DEF_HTTP_CONNECTION_CLOSE = "Close"; static const std::string DEF_HTTP_CONTENT_TYPE_HTML = "text/html; charset=UTF-8"; cHTTP::cHTTP() { } cHTTP::~cHTTP() { } std::string cHTTP::getResponse(const std::string &_content) const { sResponse oResponse = initResponse(_content); std::stringstream oResponseText; oResponseText << std::format("{} {} {}\r\n", oResponse.version, oResponse.status, oResponse.reason); oResponseText << std::format("Connection: {}\r\n", oResponse.connection); oResponseText << std::format("Content-Type: {}\r\n", oResponse.contentType); oResponseText << std::format("Content-Length: {}\r\n", oResponse.contentLength); oResponseText << "\r\n"; oResponseText << oResponse.contentText; oResponseText << "\r\n"; return oResponseText.str(); } cHTTP::sResponse cHTTP::initResponse(const std::string &_content) const { sResponse oResponse; oResponse.version = DEF_HTTP_VERSION_1_1; oResponse.status = DEF_HTTP_STATUS_200; oResponse.reason = DEF_HTTP_REASON_OK; oResponse.connection = DEF_HTTP_CONNECTION_CLOSE; oResponse.contentType = DEF_HTTP_CONTENT_TYPE_HTML; oResponse.contentLength = (int)_content.size(); oResponse.contentText = _content; return oResponse; } ...
... #pragma once #include <string> std::string getLastErrorMsg(int _error); ...
... #include "cErrorMsg.h" #include <Windows.h> static const int DEF_WINSOCK_ERROR_MSG_LENGTH = 512; std::string getLastErrorMsg(int _error) { char oErrorMsg[DEF_WINSOCK_ERROR_MSG_LENGTH] = {0}; int oLength = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, _error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), oErrorMsg, DEF_WINSOCK_ERROR_MSG_LENGTH - 1, NULL); if (oLength > 0) { oErrorMsg[oLength - 1] = 0; } std::string oMessage = oErrorMsg; return oMessage; } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 20) add_executable(${PROJECT_NAME} main.cpp cServer.cpp cServerInit.cpp cServerSocket.cpp cServerClient.cpp cServerApp.cpp cHTTP.cpp cErrorMsg.cpp cString.cpp ) target_link_libraries(${PROJECT_NAME} ws2_32 ) ...
... rdvcpp.exe ...
... #include "cServer.h" int main(int _argc, char **_argv) { cServer oServer; oServer.run(); return 0; } ...
... #pragma once #include <string> class cServerApp { public: explicit cServerApp(); ~cServerApp(); void run(const std::string &_request, std::string &_response) const; }; ...
... #include "cServerApp.h" #include "cHTTP.h" #include "cHttpApp.h" // http static const std::string DEF_HTTP_CONTENT_TYPE_HTML = "text/html; charset=UTF-8"; cServerApp::cServerApp() { } cServerApp::~cServerApp() { } void cServerApp::run(const std::string &_request, std::string &_response) const { cHTTP oHTTP; cHTTP::sRequest oRequestHTTP; if (oHTTP.analyzeRequestHTTP(oRequestHTTP, _request)) { cHttpApp oApp; std::string oResponse; cHTTP::STATUS_CODE oStatusCode = HTTP_STATUS_CODE::OK_200; std::string oContentType = DEF_HTTP_CONTENT_TYPE_HTML; oApp.run(oRequestHTTP, oResponse, oContentType, oStatusCode); _response = oHTTP.getResponse(oResponse, oContentType, oStatusCode); } else { _response = "Un probleme a ete rencontre."; } } ...
... #pragma once #include "cHttpStatusCode.h" #include <string> class cHTTP { public: struct sRequest { std::string method; std::string uri; std::string version; }; struct sResponse { std::string version; int status; std::string reason; std::string connection; std::string contentType; int contentLength; std::string contentText; }; using STATUS_CODE = HTTP_STATUS_CODE::eValues; public: cHTTP(); ~cHTTP(); bool analyzeRequestHTTP(sRequest &_requestHTTP, const std::string &_request) const; std::string getResponse(const std::string &_contentText, const std::string &_contentType, const STATUS_CODE &_statusCode) const; bool isGET(const sRequest &_requestHTTP) const; bool isPOST(const sRequest &_requestHTTP) const; private: bool isMethodAccepted(const std::string &_methodHTTP) const; bool isVersionAccepted(const std::string &_versionHTTP) const; sResponse initResponse(const std::string &_contentText, const std::string &_contentType, const STATUS_CODE &_statusCode) const; }; ...
... #include "cHTTP.h" #include "cString.h" #include <format> #include <sstream> #include <iostream> // http static const std::string DEF_HTTP_VERSION_1_0 = "HTTP/1.0"; static const std::string DEF_HTTP_VERSION_1_1 = "HTTP/1.1"; static const std::string DEF_HTTP_VERSION_2_0 = "HTTP/2.0"; // static const std::string DEF_HTTP_CONNECTION_CLOSE = "Close"; // static const std::string DEF_HTTP_METHOD_GET = "GET"; static const std::string DEF_HTTP_METHOD_POST = "POST"; // request static const int DEF_REQUEST_LIMIT_SIZE = 100; static const int DEF_REQUEST_HEADER_SIZE = 256; static const std::string DEF_REQUEST_SEP_SPACE = " "; static const std::string DEF_REQUEST_SEP_CRLF = "\r\n"; cHTTP::cHTTP() { } cHTTP::~cHTTP() { } bool cHTTP::analyzeRequestHTTP(sRequest &_requestHTTP, const std::string &_request) const { const std::string oRequestHeader = _request.substr(0, DEF_REQUEST_HEADER_SIZE); // method size_t oMethodStart = 0; size_t oMethodEnd = oRequestHeader.find(DEF_REQUEST_SEP_SPACE, oMethodStart); if (oMethodEnd == std::string::npos) { std::cout << "[Error]:La methode de la requete HTTP n'est pas determinee." << "|request=" << cString(oRequestHeader).escape(DEF_REQUEST_LIMIT_SIZE) << std::endl; return false; } std::string oMethod = oRequestHeader.substr(oMethodStart, oMethodEnd - oMethodStart); if (!isMethodAccepted(oMethod)) { std::cout << "[Error]:La methode de la requete HTTP n'est pas supportee." << "|request=" << cString(oRequestHeader).escape(DEF_REQUEST_LIMIT_SIZE) << std::endl; return false; } // uri size_t oUriStart = oMethodEnd + DEF_REQUEST_SEP_SPACE.size(); size_t oUriEnd = oRequestHeader.find(DEF_REQUEST_SEP_SPACE, oUriStart); if (oUriEnd == std::string::npos) { std::cout << "[Error]:L'uri de la requete HTTP n'est pas determinee." << "|request=" << cString(oRequestHeader).escape(DEF_REQUEST_LIMIT_SIZE) << std::endl; return false; } std::string oUri = oRequestHeader.substr(oUriStart, oUriEnd - oUriStart); // version size_t oVersionStart = oUriEnd + DEF_REQUEST_SEP_SPACE.size(); size_t oVersionEnd = oRequestHeader.find(DEF_REQUEST_SEP_CRLF, oVersionStart); if (oVersionEnd == std::string::npos) { std::cout << "[Error]:La version de la requete HTTP n'est pas determinee." << "|request=" << cString(oRequestHeader).escape(DEF_REQUEST_LIMIT_SIZE) << std::endl; return false; } std::string oVersion = oRequestHeader.substr(oVersionStart, oVersionEnd - oVersionStart); if (!isVersionAccepted(oVersion)) { std::cout << "[Error]:La version de la requete HTTP n'est pas supportee." << "|request=" << cString(oRequestHeader).escape(DEF_REQUEST_LIMIT_SIZE) << std::endl; return false; } _requestHTTP.method = oMethod; _requestHTTP.uri = oUri; _requestHTTP.version = oVersion; return true; } std::string cHTTP::getResponse(const std::string &_contentText, const std::string &_contentType, const STATUS_CODE &_statusCode) const { sResponse oResponse = initResponse(_contentText, _contentType, _statusCode); std::stringstream oResponseText; oResponseText << std::format("{} {} {}\r\n", oResponse.version, oResponse.status, oResponse.reason); oResponseText << std::format("Connection: {}\r\n", oResponse.connection); oResponseText << std::format("Content-Type: {}\r\n", oResponse.contentType); oResponseText << std::format("Content-Length: {}\r\n", oResponse.contentLength); oResponseText << "\r\n"; oResponseText << oResponse.contentText; oResponseText << "\r\n"; return oResponseText.str(); } bool cHTTP::isGET(const sRequest &_requestHTTP) const { return (_requestHTTP.method == DEF_HTTP_METHOD_GET); } bool cHTTP::isPOST(const sRequest &_requestHTTP) const { return (_requestHTTP.method == DEF_HTTP_METHOD_POST); } bool cHTTP::isMethodAccepted(const std::string &_methodHTTP) const { if ((_methodHTTP == DEF_HTTP_METHOD_GET) || (_methodHTTP == DEF_HTTP_METHOD_POST)) { return true; } return false; } bool cHTTP::isVersionAccepted(const std::string &_versionHTTP) const { if ((_versionHTTP == DEF_HTTP_VERSION_1_0) || (_versionHTTP == DEF_HTTP_VERSION_1_1) || (_versionHTTP == DEF_HTTP_VERSION_2_0)) { return true; } return false; } cHTTP::sResponse cHTTP::initResponse(const std::string &_contentText, const std::string &_contentType, const STATUS_CODE &_statusCode) const { sResponse oResponse; oResponse.version = DEF_HTTP_VERSION_1_1; oResponse.status = _statusCode; oResponse.reason = HTTP_STATUS_REASON(_statusCode); oResponse.connection = DEF_HTTP_CONNECTION_CLOSE; oResponse.contentType = _contentType; oResponse.contentLength = (int)_contentText.size(); oResponse.contentText = _contentText; return oResponse; } ...
... #pragma once #include "cHTTP.h" #include <string> class cHttpApp { public: using sRequest = cHTTP::sRequest; using STATUS_CODE = cHTTP::STATUS_CODE; public: explicit cHttpApp(); ~cHttpApp(); void run(const sRequest &_requestHTTP, std::string &_responseText, std::string &_contentType, STATUS_CODE &_statusCode) const; }; ...
... #include "cHttpApp.h" #include "cHttpGet.h" cHttpApp::cHttpApp() { } cHttpApp::~cHttpApp() { } void cHttpApp::run(const sRequest &_requestHTTP, std::string &_responseText, std::string &_contentType, STATUS_CODE &_statusCode) const { cHTTP oHTTP; if (oHTTP.isGET(_requestHTTP)) { cHttpGet oGet; oGet.run(_requestHTTP, _responseText, _contentType, _statusCode); } else if (oHTTP.isPOST(_requestHTTP)) { _responseText = "<h1>Bonjour tout le monde POST</h1>"; } else { _responseText = "Un problème a été rencontré."; } } ...
... #pragma once #include "cHTTP.h" #include <string> class cHttpGet { public: using sRequest = cHTTP::sRequest; using STATUS_CODE = cHTTP::STATUS_CODE; public: explicit cHttpGet(); ~cHttpGet(); void run(const sRequest &_requestHTTP, std::string &_responseText, std::string &_contentType, STATUS_CODE &_statusCode) const; }; ...
... #include "cHttpGet.h" #include "cFile.h" #include "cMimeType.h" #include <iostream> static const std::string DEF_SERVER_HTTP_ROOT = "../../webroot"; cHttpGet::cHttpGet() { } cHttpGet::~cHttpGet() { } void cHttpGet::run(const sRequest &_requestHTTP, std::string &_responseText, std::string &_contentType, STATUS_CODE &_statusCode) const { std::string oFilename = DEF_SERVER_HTTP_ROOT + _requestHTTP.uri; cFile oFile(oFilename); if (!oFile.exitsFile()) { _statusCode = HTTP_STATUS_CODE::NotFound_404; std::cout << "[Error]:La ressource n'a pas ete trouvee." << "|filename=" << oFilename << std::endl; return; } std::string oExtension = oFile.getExtension(); _contentType = MIME_TYPE(oExtension); _responseText = oFile.readBin(); } ...
... #pragma once #include <string> std::string MIME_TYPE(const std::string &_extension); ...
... #include "cMimeType.h" #include <map> #include <iostream> static const std::map<std::string, std::string> gMimeType = { ... {"3gpp", "audio/3gpp"}, {"jpm", "video/jpm"}, {"mp3", "audio/mp3"}, {"rtf", "text/rtf"}, {"wav", "audio/wave"}, {"xml", "text/xml"}, ... }; std::string MIME_TYPE(const std::string &_extension) { std::string oExtention(_extension); if (oExtention[0] == '.') { oExtention.erase(0, 1); } std::map<std::string, std::string>::const_iterator it; for (it = gMimeType.begin(); it != gMimeType.end(); ++it) { if (it->first == oExtention) { return it->second; } } std::cout << "[Error]:Le mimetype du fichier est inconnu." << "|extension=" << _extension << std::endl; return "text/html"; } ...
... #pragma once #include <string> struct HTTP_STATUS_CODE { enum eValues { ... // Information responses Continue_100 = 100, SwitchingProtocol_101 = 101, Processing_102 = 102, EarlyHints_103 = 103, ... }; }; std::string HTTP_STATUS_REASON(HTTP_STATUS_CODE::eValues _statusCode); ...
... #include "cHttpStatusCode.h" #include <iostream> std::string HTTP_STATUS_REASON(HTTP_STATUS_CODE::eValues _statusCode) { switch (_statusCode) { ... case HTTP_STATUS_CODE::Continue_100: return "Continue"; case HTTP_STATUS_CODE::SwitchingProtocol_101: return "Switching Protocol"; case HTTP_STATUS_CODE::Processing_102: return "Processing"; case HTTP_STATUS_CODE::EarlyHints_103: return "Early Hints"; ... default: case HTTP_STATUS_CODE::InternalServerError_500: { std::cout << "[Error]:Le status de la requête HTTP est inconnu." << "|statusCode=" << _statusCode << std::endl; return "Internal Server Error"; } } } ...
... cmake_minimum_required(VERSION 3.10.0) project(rdvcpp VERSION 0.1.0 LANGUAGES C CXX) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 20) add_executable(${PROJECT_NAME} main.cpp cServer.cpp cServerInit.cpp cServerSocket.cpp cServerClient.cpp cServerApp.cpp cHTTP.cpp cHttpApp.cpp cHttpGet.cpp cHttpStatusCode.cpp cMimeType.cpp cErrorMsg.cpp cString.cpp cFile.cpp ) target_link_libraries(${PROJECT_NAME} ws2_32 ) ...
... rdvcpp.exe ...
... GET /index.html HTTP/1.1 Host: localhost:5555 Connection: keep-alive sec-ch-ua: "Google Chrome";v="135", "Not-A.Brand";v="8", "Chromium";v="135" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br, zstd Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6,zh;q=0.5 Cookie: PHPSESSID=g5eglo9gq2jm7c0o3nu193ig13 ...
... HTTP/1.1 200 OK Connection: Close Content-Type: text/html Content-Length: 487 <!DOCTYPE html> <html lang="fr"> <head> <title>ReadyCPP | Serveur HTTP</title> <meta charset="UTF-8" /> <link rel="shortcut icon" type="image/png" href="/data/img/logo.png" /> <meta name="viewport" content="width=device-width, maximum-scale=1.0, minimum-scale=1.0, initial-scale=1.0, user-scalable=no" /> <link rel="stylesheet" href="/css/styles.css" /> </head> <body> <h1>Bonjour tout le monde</h1> </body> </html> ...
... HTTP/1.1 200 OK Connection: Close Content-Type: image/png Content-Length: 24318 xPNG xxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxx ...
... HTTP/1.1 200 OK Connection: Close Content-Type: text/css Content-Length: 50 body { background-color: darkslategray; } ...
... HTTP/1.1 404 Not Found Connection: Close Content-Type: text/html; charset=UTF-8 Content-Length: 0 ...