Elysia Tools

Parcourez outils, exemples, explications visuelles et guides thématiques dans un espace clair.

Catégories populaires

Dossiers

Langue
ZHDERUPTENFRES

Elysia Tools

Navigation mobile

C++

Programmation Réseau Windows - Exemples C++

Exemples complets de programmation réseau en C++ pour plateforme Windows incluant requêtes HTTP, sockets TCP et implémentation serveur HTTP

Exemples

Entrées de cette collection

Code sourcecppIntermédiaire

Requêtes HTTP GET/POST

Envoyer requêtes HTTP GET et POST utilisant API WinINet avec gestion d'erreurs et analyse de réponses

Difficulté

5/10

Temps estimé

20 min

Étiquettes

cpp, networking, http, windows

Prérequis

WinINet API, HTTP protocol, Windows networking

cpp
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
#include <wininet.h>
#include <sstream>
#include <map>
#include <algorithm>
#include <mutex>

#pragma comment(lib, "wininet.lib")

// HTTP Response structure
struct HttpResponse {
    std::string statusCode;
    std::string statusText;
    std::map<std::string, std::string> headers;
    std::string body;
    bool success;

    HttpResponse() : success(false) {}
};

// 1. Basic HTTP GET request
HttpResponse HttpGet(const std::string& url, const std::map<std::string, std::string>& headers = {}) {
    std::cout << "=== HTTP GET Request ===" << std::endl;
    std::cout << "URL: " << url << std::endl;

    HttpResponse response;

    try {
        // Parse URL components
        DWORD serviceType;
        std::string serverName, objectName;
        INTERNET_PORT port;

        char buffer[1024];
        DWORD bufferSize = sizeof(buffer);

        if (!InternetCrackUrlA(url.c_str(), 0, 0, nullptr)) {
            DWORD error = GetLastError();
            response.statusText = "Failed to parse URL. Error: " + std::to_string(error);
            std::cout << response.statusText << std::endl;
            return response;
        }

        URL_COMPONENTSA urlComponents = {0};
        urlComponents.dwStructSize = sizeof(urlComponents);
        urlComponents.lpszHostName = buffer;
        urlComponents.dwHostNameLength = bufferSize;
        urlComponents.lpszUrlPath = buffer + bufferSize/2;
        urlComponents.dwUrlPathLength = bufferSize/2;

        if (!InternetCrackUrlA(url.c_str(), 0, 0, &urlComponents)) {
            response.statusText = "Failed to parse URL components";
            return response;
        }

        serverName = std::string(urlComponents.lpszHostName, urlComponents.dwHostNameLength);
        objectName = std::string(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength);
        serviceType = urlComponents.nScheme;
        port = urlComponents.nPort;

        if (port == 0) {
            port = (serviceType == INTERNET_SCHEME_HTTPS) ? 443 : 80;
        }

        std::cout << "Server: " << serverName << ", Port: " << port << std::endl;
        std::cout << "Object: " << objectName << std::endl;

        // Initialize WinINet
        HINTERNET hInternet = InternetOpenA(
            "C++ HTTP Client/1.0",
            INTERNET_OPEN_TYPE_DIRECT,
            NULL,
            NULL,
            0
        );

        if (!hInternet) {
            response.statusText = "Failed to initialize WinINet";
            return response;
        }

        // Connect to server
        HINTERNET hConnect = InternetConnectA(
            hInternet,
            serverName.c_str(),
            port,
            NULL,
            NULL,
            INTERNET_SERVICE_HTTP,
            0,
            0
        );

        if (!hConnect) {
            DWORD error = GetLastError();
            response.statusText = "Failed to connect to server. Error: " + std::to_string(error);
            InternetCloseHandle(hInternet);
            return response;
        }

        // Create HTTP request
        DWORD flags = (serviceType == INTERNET_SCHEME_HTTPS) ? INTERNET_FLAG_SECURE : 0;
        flags |= INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE;

        HINTERNET hRequest = HttpOpenRequestA(
            hConnect,
            "GET",
            objectName.c_str(),
            HTTP_VERSIONA,
            NULL,
            NULL,
            flags,
            0
        );

        if (!hRequest) {
            response.statusText = "Failed to create HTTP request";
            InternetCloseHandle(hConnect);
            InternetCloseHandle(hInternet);
            return response;
        }

        // Add custom headers
        for (const auto& header : headers) {
            std::string headerLine = header.first + ": " + header.second;
            HttpAddRequestHeadersA(hRequest, headerLine.c_str(), -1, HTTP_ADDREQ_FLAG_ADD);
        }

        // Send request
        if (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) {
            DWORD error = GetLastError();
            response.statusText = "Failed to send HTTP request. Error: " + std::to_string(error);
            InternetCloseHandle(hRequest);
            InternetCloseHandle(hConnect);
            InternetCloseHandle(hInternet);
            return response;
        }

        // Get status code
        DWORD statusCode = 0;
        DWORD statusCodeSize = sizeof(statusCode);
        HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
                      &statusCode, &statusCodeSize, NULL);
        response.statusCode = std::to_string(statusCode);

        // Get status text
        char statusText[256] = {0};
        DWORD statusTextSize = sizeof(statusText);
        HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_TEXT,
                      statusText, &statusTextSize, NULL);
        response.statusText = statusText;

        std::cout << "Status: " << statusCode << " " << statusText << std::endl;

        // Get response headers
        char headersBuffer[4096] = {0};
        DWORD headersSize = sizeof(headersBuffer);
        HttpQueryInfoA(hRequest, HTTP_QUERY_RAW_HEADERS_CRLF,
                      headersBuffer, &headersSize, NULL);

        std::istringstream headersStream(headersBuffer);
        std::string headerLine;
        while (std::getline(headersStream, headerLine)) {
            size_t colonPos = headerLine.find(':');
            if (colonPos != std::string::npos) {
                std::string key = headerLine.substr(0, colonPos);
                std::string value = headerLine.substr(colonPos + 1);

                // Trim whitespace
                key.erase(0, key.find_first_not_of(" \t"));
                key.erase(key.find_last_not_of(" \t") + 1);
                value.erase(0, value.find_first_not_of(" \t"));
                value.erase(value.find_last_not_of(" \t") + 1);

                response.headers[key] = value;
            }
        }

        // Read response body
        DWORD bytesRead;
        char bodyBuffer[8192];
        std::string responseBody;

        while (InternetReadFile(hRequest, bodyBuffer, sizeof(bodyBuffer) - 1, &bytesRead) && bytesRead > 0) {
            bodyBuffer[bytesRead] = '\0';
            responseBody += bodyBuffer;
        }

        response.body = responseBody;
        response.success = (statusCode >= 200 && statusCode < 300);

        std::cout << "Response headers received: " << response.headers.size() << std::endl;
        std::cout << "Response body size: " << responseBody.length() << " bytes" << std::endl;

        // Cleanup
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);

    } catch (const std::exception& e) {
        response.statusText = "Exception occurred: " + std::string(e.what());
        std::cout << response.statusText << std::endl;
    }

    return response;
}

// 2. HTTP POST request with JSON data
HttpResponse HttpPost(const std::string& url, const std::string& postData,
                     const std::map<std::string, std::string>& headers = {}) {
    std::cout << "\n=== HTTP POST Request ===" << std::endl;
    std::cout << "URL: " << url << std::endl;
    std::cout << "Data size: " << postData.length() << " bytes" << std::endl;

    HttpResponse response;

    try {
        // Parse URL (reuse code from GET)
        DWORD serviceType;
        std::string serverName, objectName;
        INTERNET_PORT port = 80;

        URL_COMPONENTSA urlComponents = {0};
        urlComponents.dwStructSize = sizeof(urlComponents);
        char hostBuffer[512], pathBuffer[1024];
        urlComponents.lpszHostName = hostBuffer;
        urlComponents.dwHostNameLength = sizeof(hostBuffer);
        urlComponents.lpszUrlPath = pathBuffer;
        urlComponents.dwUrlPathLength = sizeof(pathBuffer);

        if (!InternetCrackUrlA(url.c_str(), 0, 0, &urlComponents)) {
            response.statusText = "Failed to parse URL";
            return response;
        }

        serverName = std::string(urlComponents.lpszHostName, urlComponents.dwHostNameLength);
        objectName = std::string(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength);
        serviceType = urlComponents.nScheme;
        port = (urlComponents.nPort == 0) ?
               ((serviceType == INTERNET_SCHEME_HTTPS) ? 443 : 80) : urlComponents.nPort;

        // Initialize WinINet
        HINTERNET hInternet = InternetOpenA(
            "C++ HTTP Client/1.0",
            INTERNET_OPEN_TYPE_DIRECT,
            NULL,
            NULL,
            0
        );

        if (!hInternet) {
            response.statusText = "Failed to initialize WinINet";
            return response;
        }

        // Connect to server
        HINTERNET hConnect = InternetConnectA(
            hInternet,
            serverName.c_str(),
            port,
            NULL,
            NULL,
            INTERNET_SERVICE_HTTP,
            0,
            0
        );

        if (!hConnect) {
            response.statusText = "Failed to connect to server";
            InternetCloseHandle(hInternet);
            return response;
        }

        // Create HTTP request
        DWORD flags = (serviceType == INTERNET_SCHEME_HTTPS) ? INTERNET_FLAG_SECURE : 0;
        flags |= INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE;

        HINTERNET hRequest = HttpOpenRequestA(
            hConnect,
            "POST",
            objectName.c_str(),
            HTTP_VERSIONA,
            NULL,
            NULL,
            flags,
            0
        );

        if (!hRequest) {
            response.statusText = "Failed to create HTTP request";
            InternetCloseHandle(hConnect);
            InternetCloseHandle(hInternet);
            return response;
        }

        // Add headers
        std::string contentTypeHeader = "Content-Type: application/json";
        HttpAddRequestHeadersA(hRequest, contentTypeHeader.c_str(), -1, HTTP_ADDREQ_FLAG_ADD);

        std::string contentLengthHeader = "Content-Length: " + std::to_string(postData.length());
        HttpAddRequestHeadersA(hRequest, contentLengthHeader.c_str(), -1, HTTP_ADDREQ_FLAG_ADD);

        for (const auto& header : headers) {
            std::string headerLine = header.first + ": " + header.second;
            HttpAddRequestHeadersA(hRequest, headerLine.c_str(), -1, HTTP_ADDREQ_FLAG_ADD);
        }

        // Send POST request
        if (!HttpSendRequestA(hRequest, NULL, 0, (LPVOID)postData.c_str(), postData.length())) {
            DWORD error = GetLastError();
            response.statusText = "Failed to send POST request. Error: " + std::to_string(error);
            InternetCloseHandle(hRequest);
            InternetCloseHandle(hConnect);
            InternetCloseHandle(hInternet);
            return response;
        }

        // Get response (reuse code from GET)
        DWORD statusCode = 0;
        DWORD statusCodeSize = sizeof(statusCode);
        HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
                      &statusCode, &statusCodeSize, NULL);
        response.statusCode = std::to_string(statusCode);

        char statusText[256] = {0};
        DWORD statusTextSize = sizeof(statusText);
        HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_TEXT,
                      statusText, &statusTextSize, NULL);
        response.statusText = statusText;

        std::cout << "Status: " << statusCode << " " << statusText << std::endl;

        // Get headers and body (same as GET)
        char headersBuffer[4096] = {0};
        DWORD headersSize = sizeof(headersBuffer);
        HttpQueryInfoA(hRequest, HTTP_QUERY_RAW_HEADERS_CRLF,
                      headersBuffer, &headersSize, NULL);

        std::istringstream headersStream(headersBuffer);
        std::string headerLine;
        while (std::getline(headersStream, headerLine)) {
            size_t colonPos = headerLine.find(':');
            if (colonPos != std::string::npos) {
                std::string key = headerLine.substr(0, colonPos);
                std::string value = headerLine.substr(colonPos + 1);

                key.erase(0, key.find_first_not_of(" \t"));
                key.erase(key.find_last_not_of(" \t") + 1);
                value.erase(0, value.find_first_not_of(" \t"));
                value.erase(value.find_last_not_of(" \t") + 1);

                response.headers[key] = value;
            }
        }

        // Read response body
        DWORD bytesRead;
        char bodyBuffer[8192];
        std::string responseBody;

        while (InternetReadFile(hRequest, bodyBuffer, sizeof(bodyBuffer) - 1, &bytesRead) && bytesRead > 0) {
            bodyBuffer[bytesRead] = '\0';
            responseBody += bodyBuffer;
        }

        response.body = responseBody;
        response.success = (statusCode >= 200 && statusCode < 300);

        std::cout << "Response received successfully" << std::endl;

        // Cleanup
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);

    } catch (const std::exception& e) {
        response.statusText = "Exception occurred: " + std::string(e.what());
        std::cout << response.statusText << std::endl;
    }

    return response;
}

// 3. Download file from URL
bool DownloadFile(const std::string& url, const std::string& filePath) {
    std::cout << "\n=== File Download ===" << std::endl;
    std::cout << "URL: " << url << std::endl;
    std::cout << "Save to: " << filePath << std::endl;

    try {
        // Parse URL
        URL_COMPONENTSA urlComponents = {0};
        urlComponents.dwStructSize = sizeof(urlComponents);
        char hostBuffer[512], pathBuffer[1024];
        urlComponents.lpszHostName = hostBuffer;
        urlComponents.dwHostNameLength = sizeof(hostBuffer);
        urlComponents.lpszUrlPath = pathBuffer;
        urlComponents.dwUrlPathLength = sizeof(pathBuffer);

        if (!InternetCrackUrlA(url.c_str(), 0, 0, &urlComponents)) {
            std::cout << "Failed to parse URL" << std::endl;
            return false;
        }

        std::string serverName(hostBuffer, urlComponents.dwHostNameLength);
        std::string objectName(pathBuffer, urlComponents.dwUrlPathLength);
        INTERNET_PORT port = (urlComponents.nPort == 0) ?
                           ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) ? 443 : 80) : urlComponents.nPort;

        // Initialize WinINet
        HINTERNET hInternet = InternetOpenA(
            "C++ File Downloader/1.0",
            INTERNET_OPEN_TYPE_DIRECT,
            NULL,
            NULL,
            0
        );

        if (!hInternet) {
            std::cout << "Failed to initialize WinINet" << std::endl;
            return false;
        }

        // Connect and open URL
        HINTERNET hUrl = InternetOpenUrlA(
            hInternet,
            url.c_str(),
            NULL,
            0,
            INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE |
            ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) ? INTERNET_FLAG_SECURE : 0),
            0
        );

        if (!hUrl) {
            DWORD error = GetLastError();
            std::cout << "Failed to open URL. Error: " << error << std::endl;
            InternetCloseHandle(hInternet);
            return false;
        }

        // Get file size
        DWORD fileSize = 0;
        DWORD fileSizeSize = sizeof(fileSize);
        HttpQueryInfoA(hUrl, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER,
                      &fileSize, &fileSizeSize, NULL);

        if (fileSize > 0) {
            std::cout << "File size: " << fileSize << " bytes" << std::endl;
        }

        // Create file
        HANDLE hFile = CreateFileA(
            filePath.c_str(),
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
        );

        if (hFile == INVALID_HANDLE_VALUE) {
            std::cout << "Failed to create file" << std::endl;
            InternetCloseHandle(hUrl);
            InternetCloseHandle(hInternet);
            return false;
        }

        // Download file
        DWORD bytesRead;
        DWORD totalBytes = 0;
        char buffer[8192];
        DWORD startTime = GetTickCount();

        std::cout << "Downloading..." << std::endl;

        while (InternetReadFile(hUrl, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
            DWORD bytesWritten;
            if (!WriteFile(hFile, buffer, bytesRead, &bytesWritten, NULL) || bytesWritten != bytesRead) {
                std::cout << "Failed to write to file" << std::endl;
                CloseHandle(hFile);
                InternetCloseHandle(hUrl);
                InternetCloseHandle(hInternet);
                return false;
            }

            totalBytes += bytesRead;

            // Show progress every 1MB
            if (totalBytes % (1024 * 1024) == 0 || bytesRead < sizeof(buffer)) {
                DWORD elapsed = GetTickCount() - startTime;
                double speed = totalBytes / (elapsed / 1000.0) / 1024.0; // KB/s

                std::cout << "Downloaded: " << totalBytes << " bytes";
                if (fileSize > 0) {
                    double progress = (double)totalBytes / fileSize * 100.0;
                    std::cout << " (" << progress << "% complete)";
                }
                std::cout << ", Speed: " << speed << " KB/s" << std::endl;
            }
        }

        DWORD elapsed = GetTickCount() - startTime;
        double avgSpeed = totalBytes / (elapsed / 1000.0) / 1024.0;

        std::cout << "Download completed!" << std::endl;
        std::cout << "Total bytes: " << totalBytes << std::endl;
        std::cout << "Average speed: " << avgSpeed << " KB/s" << std::endl;
        std::cout << "Time taken: " << elapsed / 1000.0 << " seconds" << std::endl;

        // Cleanup
        CloseHandle(hFile);
        InternetCloseHandle(hUrl);
        InternetCloseHandle(hInternet);

        return true;

    } catch (const std::exception& e) {
        std::cout << "Exception during download: " << e.what() << std::endl;
        return false;
    }
}

// 4. HTTP request with timeout
HttpResponse HttpGetWithTimeout(const std::string& url, int timeoutSeconds = 30) {
    std::cout << "\n=== HTTP GET with Timeout ===" << std::endl;
    std::cout << "URL: " << url << std::endl;
    std::cout << "Timeout: " << timeoutSeconds << " seconds" << std::endl;

    HttpResponse response;

    try {
        // Parse URL
        URL_COMPONENTSA urlComponents = {0};
        urlComponents.dwStructSize = sizeof(urlComponents);
        char hostBuffer[512], pathBuffer[1024];
        urlComponents.lpszHostName = hostBuffer;
        urlComponents.dwHostNameLength = sizeof(hostBuffer);
        urlComponents.lpszUrlPath = pathBuffer;
        urlComponents.dwUrlPathLength = sizeof(pathBuffer);

        if (!InternetCrackUrlA(url.c_str(), 0, 0, &urlComponents)) {
            response.statusText = "Failed to parse URL";
            return response;
        }

        std::string serverName(hostBuffer, urlComponents.dwHostNameLength);
        std::string objectName(pathBuffer, urlComponents.dwUrlPathLength);
        INTERNET_PORT port = (urlComponents.nPort == 0) ?
                           ((urlComponents.nScheme == INTERNET_SCHEME_HTTPS) ? 443 : 80) : urlComponents.nPort;

        // Initialize WinINet with timeout settings
        HINTERNET hInternet = InternetOpenA(
            "C++ HTTP Client/1.0",
            INTERNET_OPEN_TYPE_DIRECT,
            NULL,
            NULL,
            0
        );

        if (!hInternet) {
            response.statusText = "Failed to initialize WinINet";
            return response;
        }

        // Set timeouts
        DWORD timeoutMs = timeoutSeconds * 1000;
        InternetSetOptionA(hInternet, INTERNET_OPTION_CONNECT_TIMEOUT, &timeoutMs, sizeof(timeoutMs));
        InternetSetOptionA(hInternet, INTERNET_OPTION_SEND_TIMEOUT, &timeoutMs, sizeof(timeoutMs));
        InternetSetOptionA(hInternet, INTERNET_OPTION_RECEIVE_TIMEOUT, &timeoutMs, sizeof(timeoutMs));

        // Connect to server
        HINTERNET hConnect = InternetConnectA(
            hInternet,
            serverName.c_str(),
            port,
            NULL,
            NULL,
            INTERNET_SERVICE_HTTP,
            0,
            0
        );

        if (!hConnect) {
            DWORD error = GetLastError();
            response.statusText = "Connection failed or timeout. Error: " + std::to_string(error);
            InternetCloseHandle(hInternet);
            return response;
        }

        // Create request with timeout
        DWORD flags = (urlComponents.nScheme == INTERNET_SCHEME_HTTPS) ? INTERNET_FLAG_SECURE : 0;
        flags |= INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE;

        HINTERNET hRequest = HttpOpenRequestA(
            hConnect,
            "GET",
            objectName.c_str(),
            HTTP_VERSIONA,
            NULL,
            NULL,
            flags,
            0
        );

        if (!hRequest) {
            response.statusText = "Failed to create HTTP request";
            InternetCloseHandle(hConnect);
            InternetCloseHandle(hInternet);
            return response;
        }

        // Set request timeout
        InternetSetOptionA(hRequest, INTERNET_OPTION_SEND_TIMEOUT, &timeoutMs, sizeof(timeoutMs));
        InternetSetOptionA(hRequest, INTERNET_OPTION_RECEIVE_TIMEOUT, &timeoutMs, sizeof(timeoutMs));

        std::cout << "Sending request with " << timeoutSeconds << " second timeout..." << std::endl;
        DWORD startTime = GetTickCount();

        // Send request
        if (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) {
            DWORD error = GetLastError();
            if (error == ERROR_INTERNET_TIMEOUT) {
                response.statusText = "Request timed out after " + std::to_string(timeoutSeconds) + " seconds";
            } else {
                response.statusText = "Failed to send request. Error: " + std::to_string(error);
            }
            InternetCloseHandle(hRequest);
            InternetCloseHandle(hConnect);
            InternetCloseHandle(hInternet);
            return response;
        }

        DWORD sendTime = GetTickCount() - startTime;
        std::cout << "Request sent in " << sendTime << "ms" << std::endl;

        // Get response (reuse code from previous functions)
        DWORD statusCode = 0;
        DWORD statusCodeSize = sizeof(statusCode);
        HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
                      &statusCode, &statusCodeSize, NULL);
        response.statusCode = std::to_string(statusCode);

        char statusText[256] = {0};
        DWORD statusTextSize = sizeof(statusText);
        HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_TEXT,
                      statusText, &statusTextSize, NULL);
        response.statusText = statusText;

        // Read response with timeout
        DWORD bytesRead;
        char bodyBuffer[8192];
        std::string responseBody;
        DWORD readStartTime = GetTickCount();

        std::cout << "Reading response..." << std::endl;

        while (InternetReadFile(hRequest, bodyBuffer, sizeof(bodyBuffer) - 1, &bytesRead) && bytesRead > 0) {
            bodyBuffer[bytesRead] = '\0';
            responseBody += bodyBuffer;

            // Check if we're exceeding timeout
            DWORD currentElapsed = GetTickCount() - readStartTime;
            if (currentElapsed > timeoutMs) {
                response.statusText = "Response reading timed out after " + std::to_string(timeoutSeconds) + " seconds";
                response.statusCode = "408"; // Request Timeout
                InternetCloseHandle(hRequest);
                InternetCloseHandle(hConnect);
                InternetCloseHandle(hInternet);
                return response;
            }
        }

        DWORD readTime = GetTickCount() - readStartTime;
        std::cout << "Response read in " << readTime << "ms" << std::endl;

        response.body = responseBody;
        response.success = (statusCode >= 200 && statusCode < 300);

        std::cout << "Request completed successfully" << std::endl;

        // Cleanup
        InternetCloseHandle(hRequest);
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hInternet);

    } catch (const std::exception& e) {
        response.statusText = "Exception occurred: " + std::string(e.what());
        std::cout << response.statusText << std::endl;
    }

    return response;
}

// Helper function to print response details
void PrintResponse(const HttpResponse& response) {
    std::cout << "\n=== Response Details ===" << std::endl;
    std::cout << "Status: " << response.statusCode << " " << response.statusText << std::endl;
    std::cout << "Success: " << (response.success ? "Yes" : "No") << std::endl;
    std::cout << "Headers (" << response.headers.size() << "):" << std::endl;

    for (const auto& header : response.headers) {
        std::cout << "  " << header.first << ": " << header.second << std::endl;
    }

    std::cout << "\nBody (" << response.body.length() << " bytes):" << std::endl;
    if (response.body.length() > 500) {
        std::cout << response.body.substr(0, 250) << "..." << std::endl;
        std::cout << "(showing first 250 of " << response.body.length() << " characters)" << std::endl;
    } else {
        std::cout << response.body << std::endl;
    }
}

int main() {
    std::cout << "=== C++ Windows Networking Examples ===" << std::endl;
    std::cout << "Demonstrating HTTP requests using WinINet API\n" << std::endl;

    try {
        // Test 1: Simple GET request
        std::cout << "1. Testing HTTP GET request..." << std::endl;
        HttpResponse getResponse = HttpGet("https://httpbin.org/get");
        PrintResponse(getResponse);

        // Test 2: GET request with custom headers
        std::cout << "\n\n2. Testing GET request with custom headers..." << std::endl;
        std::map<std::string, std::string> headers = {
            {"User-Agent", "C++ WinINet Client/1.0"},
            {"Accept", "application/json"},
            {"X-Custom-Header", "Test-Value"}
        };
        HttpResponse getWithHeadersResponse = HttpGet("https://httpbin.org/headers", headers);
        PrintResponse(getWithHeadersResponse);

        // Test 3: POST request with JSON data
        std::cout << "\n\n3. Testing HTTP POST request..." << std::endl;
        std::string jsonData = R"({"name": "C++ Client", "version": "1.0", "platform": "Windows"})";
        HttpResponse postResponse = HttpPost("https://httpbin.org/post", jsonData);
        PrintResponse(postResponse);

        // Test 4: GET request with timeout
        std::cout << "\n\n4. Testing HTTP request with timeout..." << std::endl;
        HttpResponse timeoutResponse = HttpGetWithTimeout("https://httpbin.org/delay/2", 5);
        PrintResponse(timeoutResponse);

        // Test 5: Timeout test (should fail)
        std::cout << "\n\n5. Testing timeout with long delay..." << std::endl;
        HttpResponse timeoutFailResponse = HttpGetWithTimeout("https://httpbin.org/delay/10", 3);
        PrintResponse(timeoutFailResponse);

        // Test 6: File download (commented out to avoid creating files)
        /*
        std::cout << "\n\n6. Testing file download..." << std::endl;
        bool downloadSuccess = DownloadFile(
            "https://httpbin.org/bytes/1024",
            "test_download.bin"
        );
        std::cout << "Download " << (downloadSuccess ? "successful" : "failed") << std::endl;
        */

        std::cout << "\nAll networking examples completed successfully!" << std::endl;

    } catch (const std::exception& e) {
        std::cerr << "Unexpected error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
Code sourcecppIntermédiaire

Programmation Sockets TCP

Implémenter client et serveur TCP utilisant Windows Sockets (Winsock) avec gestion de connexion appropriée

Difficulté

6/10

Temps estimé

25 min

Étiquettes

cpp, networking, tcp, sockets, windows

Prérequis

Windows Sockets API, TCP/IP protocol, Multithreading

cpp
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <ws2tcpip.h>
#include <windows.h>

#pragma comment(lib, "ws2_32.lib")

// Constants
const int BUFFER_SIZE = 4096;
const int DEFAULT_PORT = 8080;
const int MAX_CLIENTS = 10;

// TCP Client class
class TcpClient {
private:
    SOCKET socket_;
    std::string serverAddress_;
    int port_;
    bool connected_;

public:
    TcpClient() : socket_(INVALID_SOCKET), port_(DEFAULT_PORT), connected_(false) {}

    ~TcpClient() {
        Disconnect();
    }

    bool Connect(const std::string& serverAddress, int port = DEFAULT_PORT) {
        serverAddress_ = serverAddress;
        port_ = port;

        std::cout << "Connecting to " << serverAddress << ":" << port << std::endl;

        // Create socket
        socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (socket_ == INVALID_SOCKET) {
            std::cout << "Failed to create socket. Error: " << WSAGetLastError() << std::endl;
            return false;
        }

        // Setup server address
        sockaddr_in serverAddr;
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_port = htons(port);

        // Convert IP address
        if (inet_pton(AF_INET, serverAddress.c_str(), &serverAddr.sin_addr) != 1) {
            std::cout << "Invalid IP address format" << std::endl;
            closesocket(socket_);
            return false;
        }

        // Connect to server
        if (connect(socket_, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
            std::cout << "Failed to connect to server. Error: " << WSAGetLastError() << std::endl;
            closesocket(socket_);
            return false;
        }

        connected_ = true;
        std::cout << "Connected to server successfully!" << std::endl;
        return true;
    }

    bool Send(const std::string& data) {
        if (!connected_) {
            std::cout << "Not connected to server" << std::endl;
            return false;
        }

        std::cout << "Sending " << data.length() << " bytes: " << data << std::endl;

        int bytesSent = send(socket_, data.c_str(), data.length(), 0);
        if (bytesSent == SOCKET_ERROR) {
            std::cout << "Failed to send data. Error: " << WSAGetLastError() << std::endl;
            return false;
        }

        if (bytesSent != (int)data.length()) {
            std::cout << "Warning: Not all data was sent. Sent: " << bytesSent << " of " << data.length() << " bytes" << std::endl;
        }

        return true;
    }

    std::string Receive() {
        if (!connected_) {
            std::cout << "Not connected to server" << std::endl;
            return "";
        }

        char buffer[BUFFER_SIZE];
        int bytesReceived = recv(socket_, buffer, BUFFER_SIZE - 1, 0);

        if (bytesReceived > 0) {
            buffer[bytesReceived] = '\0';
            std::string receivedData(buffer);
            std::cout << "Received " << bytesReceived << " bytes: " << receivedData << std::endl;
            return receivedData;
        } else if (bytesReceived == 0) {
            std::cout << "Connection closed by server" << std::endl;
            connected_ = false;
        } else {
            std::cout << "Failed to receive data. Error: " << WSAGetLastError() << std::endl;
            connected_ = false;
        }

        return "";
    }

    void Disconnect() {
        if (connected_) {
            closesocket(socket_);
            connected_ = false;
            std::cout << "Disconnected from server" << std::endl;
        }
    }

    bool IsConnected() const {
        return connected_;
    }
};

// TCP Server class
class TcpServer {
private:
    SOCKET listenSocket_;
    std::vector<std::thread> clientThreads_;
    std::vector<SOCKET> clientSockets_;
    bool running_;
    int port_;

    void HandleClient(SOCKET clientSocket, const std::string& clientAddress) {
        std::cout << "Client connected from " << clientAddress << std::endl;

        char buffer[BUFFER_SIZE];

        // Send welcome message
        std::string welcome = "Welcome to TCP Server! Connected from " + clientAddress + "\n";
        send(clientSocket, welcome.c_str(), welcome.length(), 0);

        while (running_) {
            // Receive data from client
            int bytesReceived = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0);

            if (bytesReceived > 0) {
                buffer[bytesReceived] = '\0';
                std::string receivedData(buffer);

                std::cout << "Received from " << clientAddress << ": " << receivedData << std::endl;

                // Process received data and send response
                std::string response = ProcessClientMessage(receivedData, clientAddress);

                if (send(clientSocket, response.c_str(), response.length(), 0) == SOCKET_ERROR) {
                    std::cout << "Failed to send response to " << clientAddress << std::endl;
                    break;
                }

                // Check if client wants to disconnect
                if (receivedData.find("quit") != std::string::npos ||
                    receivedData.find("exit") != std::string::npos) {
                    std::cout << "Client " << clientAddress << " requested disconnect" << std::endl;
                    break;
                }

            } else if (bytesReceived == 0) {
                std::cout << "Client " << clientAddress << " disconnected" << std::endl;
                break;
            } else {
                int error = WSAGetLastError();
                if (error != WSAEWOULDBLOCK) {
                    std::cout << "Connection error with client " << clientAddress << ". Error: " << error << std::endl;
                    break;
                }
            }

            // Small delay to prevent CPU spinning
            std::this_thread::sleep_for(std::chrono::milliseconds(10));
        }

        // Clean up client connection
        closesocket(clientSocket);

        // Remove from client list
        std::lock_guard<std::mutex> lock(clientMutex_);
        auto it = std::find(clientSockets_.begin(), clientSockets_.end(), clientSocket);
        if (it != clientSockets_.end()) {
            clientSockets_.erase(it);
        }

        std::cout << "Connection with " << clientAddress << " closed" << std::endl;
    }

    std::string ProcessClientMessage(const std::string& message, const std::string& clientAddress) {
        // Simple echo server with some additional processing
        if (message.find("time") != std::string::npos) {
            // Send current time
            time_t now = time(nullptr);
            char timeStr[100];
            strftime(timeStr, sizeof(timeStr), "%Y-%m-%d %H:%M:%S", localtime(&now));
            return std::string("Current time: ") + timeStr + "\n";
        }

        if (message.find("info") != std::string::npos) {
            // Send server info
            return std::string("TCP Server Info:\n") +
                   "Client: " + clientAddress + "\n" +
                   "Connected clients: " + std::to_string(clientSockets_.size()) + "\n" +
                   "Server running: " + (running_ ? "Yes" : "No") + "\n";
        }

        if (message.find("help") != std::string::npos) {
            return std::string("Available commands:\n") +
                   "  time    - Get current server time\n" +
                   "  info    - Get server information\n" +
                   "  echo    - Echo message back\n" +
                   "  quit    - Disconnect from server\n" +
                   "  help    - Show this help message\n";
        }

        // Default echo response
        return "Echo: " + message;
    }

    static std::mutex clientMutex_;

public:
    TcpServer() : listenSocket_(INVALID_SOCKET), running_(false), port_(DEFAULT_PORT) {}

    ~TcpServer() {
        Stop();
    }

    bool Start(int port = DEFAULT_PORT) {
        port_ = port;

        std::cout << "Starting TCP server on port " << port << std::endl;

        // Create listening socket
        listenSocket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (listenSocket_ == INVALID_SOCKET) {
            std::cout << "Failed to create listening socket. Error: " << WSAGetLastError() << std::endl;
            return false;
        }

        // Setup server address
        sockaddr_in serverAddr;
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_addr.s_addr = INADDR_ANY;
        serverAddr.sin_port = htons(port);

        // Bind socket
        if (bind(listenSocket_, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
            std::cout << "Failed to bind socket. Error: " << WSAGetLastError() << std::endl;
            closesocket(listenSocket_);
            return false;
        }

        // Listen for connections
        if (listen(listenSocket_, SOMAXCONN) == SOCKET_ERROR) {
            std::cout << "Failed to listen. Error: " << WSAGetLastError() << std::endl;
            closesocket(listenSocket_);
            return false;
        }

        running_ = true;
        std::cout << "TCP server started successfully on port " << port << std::endl;

        // Start accepting connections in a separate thread
        std::thread acceptThread(&TcpServer::AcceptConnections, this);
        acceptThread.detach();

        return true;
    }

    void AcceptConnections() {
        while (running_) {
            sockaddr_in clientAddr;
            int clientAddrSize = sizeof(clientAddr);

            // Accept connection
            SOCKET clientSocket = accept(listenSocket_, (sockaddr*)&clientAddr, &clientAddrSize);

            if (clientSocket != INVALID_SOCKET) {
                // Get client IP address
                char clientIP[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, INET_ADDRSTRLEN);
                std::string clientAddress = std::string(clientIP) + ":" + std::to_string(ntohs(clientAddr.sin_port));

                // Set socket to non-blocking mode
                u_long mode = 1; // 1 = non-blocking
                ioctlsocket(clientSocket, FIONBIO, &mode);

                {
                    std::lock_guard<std::mutex> lock(clientMutex_);
                    clientSockets_.push_back(clientSocket);
                }

                std::cout << "Accepted connection from " << clientAddress << std::endl;

                // Start client handler thread
                clientThreads_.emplace_back(&TcpServer::HandleClient, this, clientSocket, clientAddress);
            } else {
                int error = WSAGetLastError();
                if (error != WSAEWOULDBLOCK) {
                    std::cout << "Accept failed. Error: " << error << std::endl;
                }
            }

            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    }

    void Stop() {
        if (running_) {
            std::cout << "Stopping TCP server..." << std::endl;
            running_ = false;

            // Close listening socket
            if (listenSocket_ != INVALID_SOCKET) {
                closesocket(listenSocket_);
                listenSocket_ = INVALID_SOCKET;
            }

            // Close all client connections
            {
                std::lock_guard<std::mutex> lock(clientMutex_);
                for (SOCKET clientSocket : clientSockets_) {
                    closesocket(clientSocket);
                }
                clientSockets_.clear();
            }

            // Wait for all client threads to finish
            for (auto& thread : clientThreads_) {
                if (thread.joinable()) {
                    thread.join();
                }
            }

            clientThreads_.clear();
            std::cout << "TCP server stopped" << std::endl;
        }
    }

    bool IsRunning() const {
        return running_;
    }

    int GetClientCount() const {
        std::lock_guard<std::mutex> lock(clientMutex_);
        return clientSockets_.size();
    }
};

std::mutex TcpServer::clientMutex_;

// Initialize Winsock
bool InitializeWinsock() {
    WSADATA wsaData;
    int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (result != 0) {
        std::cout << "WSAStartup failed. Error: " << result << std::endl;
        return false;
    }

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        std::cout << "Winsock 2.2 not available" << std::endl;
        WSACleanup();
        return false;
    }

    std::cout << "Winsock 2.2 initialized successfully" << std::endl;
    return true;
}

// Cleanup Winsock
void CleanupWinsock() {
    WSACleanup();
    std::cout << "Winsock cleaned up" << std::endl;
}

// 1. Simple client test
void TestSimpleClient() {
    std::cout << "\n=== Simple TCP Client Test ===" << std::endl;

    TcpClient client;

    // Connect to a public echo server
    if (client.Connect("tcpbin.com", 4242)) {
        // Send test message
        std::string message = "Hello from C++ TCP Client!";
        if (client.Send(message)) {
            // Receive response
            std::string response = client.Receive();
            if (!response.empty()) {
                std::cout << "Echo response received: " << response << std::endl;
            }
        }

        // Send another message
        if (client.Send("What time is it?")) {
            std::string response = client.Receive();
            if (!response.empty()) {
                std::cout << "Second response: " << response << std::endl;
            }
        }

        client.Disconnect();
    }
}

// 2. Local server test
void TestLocalServer() {
    std::cout << "\n=== Local TCP Server Test ===" << std::endl;

    TcpServer server;

    if (server.Start(8080)) {
        std::cout << "Server started. Connect with: telnet localhost 8080" << std::endl;
        std::cout << "Available commands: time, info, help, quit\n" << std::endl;

        // Run server for 30 seconds
        std::this_thread::sleep_for(std::chrono::seconds(30));

        std::cout << "Stopping server after 30 seconds..." << std::endl;
        server.Stop();
    }
}

// 3. Client connecting to local server
void TestClientToServer() {
    std::cout << "\n=== Client to Local Server Test ===" << std::endl;

    TcpServer server;
    if (!server.Start(8081)) {
        std::cout << "Failed to start server" << std::endl;
        return;
    }

    // Give server time to start
    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    // Connect client to server
    TcpClient client;
    if (client.Connect("127.0.0.1", 8081)) {
        // Test commands
        std::vector<std::string> commands = {
            "help",
            "time",
            "info",
            "Hello Server!",
            "quit"
        };

        for (const std::string& command : commands) {
            std::cout << "\nSending: " << command << std::endl;
            if (client.Send(command + "\n")) {
                std::string response = client.Receive();
                if (!response.empty()) {
                    std::cout << "Server response: " << response << std::endl;
                }
            }

            std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }

        client.Disconnect();
    }

    server.Stop();
}

// 4. Multiple clients test
void TestMultipleClients() {
    std::cout << "\n=== Multiple Clients Test ===" << std::endl;

    TcpServer server;
    if (!server.Start(8082)) {
        std::cout << "Failed to start server" << std::endl;
        return;
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(500));

    // Create multiple client threads
    std::vector<std::thread> clientThreads;

    for (int i = 1; i <= 3; i++) {
        clientThreads.emplace_back([i]() {
            TcpClient client;
            if (client.Connect("127.0.0.1", 8082)) {
                // Send client identification
                std::string message = "Client " + std::to_string(i) + " is here!";
                client.Send(message + "\n");

                // Get welcome message
                std::string welcome = client.Receive();
                std::cout << "Client " << i << " received: " << welcome << std::endl;

                // Send a few commands
                client.Send("info\n");
                std::string info = client.Receive();
                std::cout << "Client " << i << " info: " << info << std::endl;

                client.Send("quit\n");

                client.Disconnect();
                std::cout << "Client " << i << " disconnected" << std::endl;
            }
        });
    }

    // Let clients run
    std::this_thread::sleep_for(std::chrono::seconds(5));

    // Wait for all client threads to finish
    for (auto& thread : clientThreads) {
        if (thread.joinable()) {
            thread.join();
        }
    }

    server.Stop();
}

// 5. Connection failure test
void TestConnectionFailure() {
    std::cout << "\n=== Connection Failure Test ===" << std::endl;

    TcpClient client;

    // Try to connect to non-existent server
    std::cout << "Attempting to connect to non-existent server..." << std::endl;
    if (!client.Connect("192.0.2.1", 8080)) { // RFC 5737 test address
        std::cout << "Connection failed as expected (good test)" << std::endl;
    } else {
        std::cout << "Unexpected success connecting to test address" << std::endl;
        client.Disconnect();
    }

    // Try to connect to invalid port
    std::cout << "Attempting to connect to localhost on invalid port..." << std::endl;
    if (!client.Connect("127.0.0.1", 99999)) {
        std::cout << "Connection to invalid port failed as expected (good test)" << std::endl;
    } else {
        std::cout << "Unexpected success connecting to invalid port" << std::endl;
        client.Disconnect();
    }
}

int main() {
    std::cout << "=== C++ Windows TCP Socket Examples ===" << std::endl;
    std::cout << "Demonstrating TCP client/server communication using Winsock\n" << std::endl;

    try {
        // Initialize Winsock
        if (!InitializeWinsock()) {
            return 1;
        }

        // Run all tests
        TestConnectionFailure();
        TestSimpleClient();
        TestClientToServer();
        TestMultipleClients();

        // Note: Uncomment the following to run an interactive server
        // TestLocalServer();

        std::cout << "\nAll TCP socket examples completed!" << std::endl;

        // Cleanup Winsock
        CleanupWinsock();

    } catch (const std::exception& e) {
        std::cerr << "Unexpected error: " << e.what() << std::endl;
        CleanupWinsock();
        return 1;
    }

    return 0;
}
Code sourcecppComplexe

Serveur HTTP Simple

Construire serveur HTTP basique utilisant Winsock avec analyse de requêtes et génération de réponses

Difficulté

7/10

Temps estimé

35 min

Étiquettes

cpp, networking, http, server, windows

Prérequis

Advanced Winsock, HTTP protocol, Multithreading, Web development

cpp
#include <iostream>
#include <string>
#include <map>
#include <sstream>
#include <vector>
#include <thread>
#include <regex>
#include <ctime>
#include <ws2tcpip.h>
#include <windows.h>

#pragma comment(lib, "ws2_32.lib")

// Constants
const int BUFFER_SIZE = 8192;
const int DEFAULT_PORT = 8080;
const std::string SERVER_NAME = "C++ HTTP Server/1.0";
const std::string SERVER_VERSION = "1.0";

// HTTP Request structure
struct HttpRequest {
    std::string method;
    std::string path;
    std::string version;
    std::map<std::string, std::string> headers;
    std::string body;
    std::map<std::string, std::string> queryParams;
};

// HTTP Response structure
struct HttpResponse {
    std::string version = "HTTP/1.1";
    int statusCode = 200;
    std::string statusText = "OK";
    std::map<std::string, std::string> headers;
    std::string body;

    HttpResponse() {
        headers["Server"] = SERVER_NAME;
        headers["Connection"] = "close";
        headers["Date"] = GetCurrentDateTime();
    }

    void SetContentType(const std::string& contentType) {
        headers["Content-Type"] = contentType;
    }

    void SetContentLength() {
        headers["Content-Length"] = std::to_string(body.length());
    }

    std::string ToString() {
        SetContentLength();

        std::ostringstream response;
        response << version << " " << statusCode << " " << statusText << "\r\n";

        for (const auto& header : headers) {
            response << header.first << ": " << header.second << "\r\n";
        }

        response << "\r\n" << body;
        return response.str();
    }

private:
    static std::string GetCurrentDateTime() {
        time_t now = time(nullptr);
        struct tm timeinfo;
        gmtime_s(&timeinfo, &now);

        char buffer[100];
        strftime(buffer, sizeof(buffer), "%a, %d %b %Y %H:%M:%S GMT", &timeinfo);
        return std::string(buffer);
    }
};

// 1. Parse HTTP request
HttpRequest ParseHttpRequest(const std::string& requestStr) {
    HttpRequest request;
    std::istringstream stream(requestStr);
    std::string line;

    // Parse request line
    if (std::getline(stream, line)) {
        // Remove CRLF
        line.erase(line.find_last_not_of("\r") + 1);

        std::istringstream requestLine(line);
        std::string pathWithQuery;

        requestLine >> request.method >> pathWithQuery >> request.version;

        // Parse path and query parameters
        size_t queryPos = pathWithQuery.find('?');
        if (queryPos != std::string::npos) {
            request.path = pathWithQuery.substr(0, queryPos);
            std::string queryString = pathWithQuery.substr(queryPos + 1);

            // Parse query parameters
            std::istringstream queryStream(queryString);
            std::string param;

            while (std::getline(queryStream, param, '&')) {
                size_t eqPos = param.find('=');
                if (eqPos != std::string::npos) {
                    std::string key = param.substr(0, eqPos);
                    std::string value = param.substr(eqPos + 1);
                    request.queryParams[key] = value;
                }
            }
        } else {
            request.path = pathWithQuery;
        }
    }

    // Parse headers
    while (std::getline(stream, line)) {
        line.erase(line.find_last_not_of("\r") + 1);

        if (line.empty()) {
            break; // End of headers
        }

        size_t colonPos = line.find(':');
        if (colonPos != std::string::npos) {
            std::string key = line.substr(0, colonPos);
            std::string value = line.substr(colonPos + 1);

            // Trim whitespace
            key.erase(0, key.find_first_not_of(" \t"));
            key.erase(key.find_last_not_of(" \t") + 1);
            value.erase(0, value.find_first_not_of(" \t"));
            value.erase(value.find_last_not_of(" \t") + 1);

            // Convert header name to lowercase for consistent access
            std::transform(key.begin(), key.end(), key.begin(), ::tolower);

            request.headers[key] = value;
        }
    }

    // Parse body (if present)
    std::string remaining;
    while (std::getline(stream, line)) {
        remaining += line + "\n";
    }

    if (!remaining.empty()) {
        request.body = remaining;
    }

    return request;
}

// 2. Create error responses
HttpResponse CreateErrorResponse(int statusCode, const std::string& message) {
    HttpResponse response;
    response.statusCode = statusCode;
    response.statusText = GetStatusText(statusCode);
    response.SetContentType("text/html");

    std::ostringstream html;
    html << "<!DOCTYPE html>\n";
    html << "<html>\n";
    html << "<head><title>Error " << statusCode << "</title></head>\n";
    html << "<body>\n";
    html << "<h1>Error " << statusCode << " - " << response.statusText << "</h1>\n";
    html << "<p>" << message << "</p>\n";
    html << "<hr>\n";
    html << "<address>" << SERVER_NAME << "</address>\n";
    html << "</body>\n";
    html << "</html>\n";

    response.body = html.str();
    return response;
}

// 3. Get status text for status code
std::string GetStatusText(int statusCode) {
    switch (statusCode) {
        case 200: return "OK";
        case 201: return "Created";
        case 400: return "Bad Request";
        case 401: return "Unauthorized";
        case 403: return "Forbidden";
        case 404: return "Not Found";
        case 405: return "Method Not Allowed";
        case 500: return "Internal Server Error";
        case 501: return "Not Implemented";
        default: return "Unknown";
    }
}

// 4. Handle GET request
HttpResponse HandleGetRequest(const HttpRequest& request) {
    std::cout << "Handling GET request for: " << request.path << std::endl;

    // Route handling
    if (request.path == "/") {
        return HandleRootRequest();
    } else if (request.path == "/about") {
        return HandleAboutRequest();
    } else if (request.path == "/time") {
        return HandleTimeRequest();
    } else if (request.path == "/echo") {
        return HandleEchoRequest(request);
    } else if (request.path == "/status") {
        return HandleStatusRequest();
    } else if (request.path == "/api/info") {
        return HandleApiInfoRequest(request);
    } else {
        return CreateErrorResponse(404, "The requested resource was not found on this server.");
    }
}

// 5. Handle POST request
HttpResponse HandlePostRequest(const HttpRequest& request) {
    std::cout << "Handling POST request for: " << request.path << std::endl;

    if (request.path == "/echo") {
        return HandleEchoPostRequest(request);
    } else if (request.path == "/api/data") {
        return HandleApiDataRequest(request);
    } else if (request.path == "/upload") {
        return HandleUploadRequest(request);
    } else {
        return CreateErrorResponse(404, "The requested POST endpoint was not found on this server.");
    }
}

// 6. Route handlers
HttpResponse HandleRootRequest() {
    HttpResponse response;
    response.SetContentType("text/html");

    std::ostringstream html;
    html << "<!DOCTYPE html>\n";
    html << "<html>\n";
    html << "<head>\n";
    html << "    <title>C++ HTTP Server</title>\n";
    html << "    <style>\n";
    html << "        body { font-family: Arial, sans-serif; margin: 40px; }\n";
    html << "        h1 { color: #333; }\n";
    html << "        .endpoint { background: #f5f5f5; padding: 10px; margin: 10px 0; border-radius: 5px; }\n";
    html << "        code { background: #e0e0e0; padding: 2px 4px; border-radius: 3px; }\n";
    html << "    </style>\n";
    html << "</head>\n";
    html << "<body>\n";
    html << "    <h1>Welcome to C++ HTTP Server!</h1>\n";
    html << "    <p>This is a simple HTTP server built with C++ and Winsock.</p>\n";
    html << "    <h2>Available Endpoints:</h2>\n";
    html << "    <div class='endpoint'><strong>GET /</strong> - This page</div>\n";
    html << "    <div class='endpoint'><strong>GET /about</strong> - Server information</div>\n";
    html << "    <div class='endpoint'><strong>GET /time</strong> - Current server time</div>\n";
    html << "    <div class='endpoint'><strong>GET /echo?message=hello</strong> - Echo query parameter</div>\n";
    html << "    <div class='endpoint'><strong>GET /status</strong> - Server status</div>\n";
    html << "    <div class='endpoint'><strong>GET /api/info</strong> - API information</div>\n";
    html << "    <div class='endpoint'><strong>POST /echo</strong> - Echo request body</div>\n";
    html << "    <div class='endpoint'><strong>POST /api/data</strong> - Accept JSON data</div>\n";
    html << "    <div class='endpoint'><strong>POST /upload</strong> - File upload simulation</div>\n";
    html << "</body>\n";
    html << "</html>\n";

    response.body = html.str();
    return response;
}

HttpResponse HandleAboutRequest() {
    HttpResponse response;
    response.SetContentType("text/html");

    std::ostringstream html;
    html << "<!DOCTYPE html>\n";
    html << "<html>\n";
    html << "<head><title>About - C++ HTTP Server</title></head>\n";
    html << "<body>\n";
    html << "<h1>About This Server</h1>\n";
    html << "<ul>\n";
    html << "<li><strong>Name:</strong> " << SERVER_NAME << "</li>\n";
    html << "<li><strong>Version:</strong> " << SERVER_VERSION << "</li>\n";
    html << "<li><strong>Protocol:</strong> HTTP/1.1</li>\n";
    html << "<li><strong>Platform:</strong> Windows (Winsock)</li>\n";
    html << "<li><strong>Language:</strong> C++</li>\n";
    html << "</ul>\n";
    html << "<p>Built as a demonstration of basic HTTP server functionality.</p>\n";
    html << "</body>\n";
    html << "</html>\n";

    response.body = html.str();
    return response;
}

HttpResponse HandleTimeRequest() {
    HttpResponse response;
    response.SetContentType("text/plain");

    time_t now = time(nullptr);
    char buffer[100];
    ctime_s(buffer, sizeof(buffer), &now);

    response.body = std::string("Current server time: ") + buffer;
    return response;
}

HttpResponse HandleEchoRequest(const HttpRequest& request) {
    HttpResponse response;
    response.SetContentType("text/html");

    std::ostringstream html;
    html << "<!DOCTYPE html>\n";
    html << "<html>\n";
    html << "<head><title>Echo Response</title></head>\n";
    html << "<body>\n";
    html << "<h1>Echo Request</h1>\n";
    html << "<p><strong>Path:</strong> " << request.path << "</p>\n";
    html << "<p><strong>Method:</strong> " << request.method << "</p>\n";
    html << "<p><strong>Query Parameters:</strong></p>\n";
    html << "<ul>\n";

    for (const auto& param : request.queryParams) {
        html << "<li><em>" << param.first << "</em> = " << param.second << "</li>\n";
    }

    if (request.queryParams.empty()) {
        html << "<li><em>No query parameters found</em></li>\n";
    }

    html << "</ul>\n";
    html << "</body>\n";
    html << "</html>\n";

    response.body = html.str();
    return response;
}

HttpResponse HandleEchoPostRequest(const HttpRequest& request) {
    HttpResponse response;
    response.SetContentType("text/html");

    std::ostringstream html;
    html << "<!DOCTYPE html>\n";
    html << "<html>\n";
    html << "<head><title>POST Echo Response</title></head>\n";
    html << "<body>\n";
    html << "<h1>POST Request Echo</h1>\n";
    html << "<p><strong>Request Body:</strong></p>\n";
    html << "<pre>" << request.body << "</pre>\n";
    html << "<p><strong>Body Length:</strong> " << request.body.length() << " bytes</p>\n";
    html << "</body>\n";
    html << "</html>\n";

    response.body = html.str();
    return response;
}

HttpResponse HandleStatusRequest() {
    HttpResponse response;
    response.SetContentType("application/json");

    std::ostringstream json;
    json << "{\n";
    json << "  \"status\": \"running\",\n";
    json << "  \"uptime\": \"" << GetUptime() << "\",\n";
    json << "  \"memory\": \"" << GetMemoryUsage() << "\",\n";
    json << "  \"connections\": \"" << GetConnectionCount() << "\"\n";
    json << "}\n";

    response.body = json.str();
    return response;
}

HttpResponse HandleApiInfoRequest(const HttpRequest& request) {
    HttpResponse response;
    response.SetContentType("application/json");

    std::ostringstream json;
    json << "{\n";
    json << "  \"name\": \"" << SERVER_NAME << "\",\n";
    json << "  \"version\": \"" << SERVER_VERSION << "\",\n";
    json << "  \"endpoints\": [\n";
    json << "    \"GET /\",\n";
    json << "    \"GET /about\",\n";
    json << "    \"GET /time\",\n";
    json << "    \"GET /echo\",\n";
    json << "    \"GET /status\",\n";
    json << "    \"POST /echo\",\n";
    json << "    \"POST /api/data\",\n";
    json << "    \"POST /upload\"\n";
    json << "  ],\n";
    json << "  \"request\": {\n";
    json << "    \"method\": \"" << request.method << "\",\n";
    json << "    \"path\": \"" << request.path << "\",\n";
    json << "    \"query\": {";

    bool first = true;
    for (const auto& param : request.queryParams) {
        if (!first) json << ",";
        json << "\"" << param.first << "\": \"" << param.second << "\"";
        first = false;
    }

    json << "}\n";
    json << "  }\n";
    json << "}\n";

    response.body = json.str();
    return response;
}

HttpResponse HandleApiDataRequest(const HttpRequest& request) {
    HttpResponse response;
    response.SetContentType("application/json");

    std::ostringstream json;
    json << "{\n";
    json << "  \"status\": \"received\",\n";
    json << "  \"message\": \"Data received successfully\",\n";
    json << "  \"data\": \"" << request.body << "\",\n";
    json << "  \"timestamp\": \"" << GetCurrentDateTime() << "\"\n";
    json << "}\n";

    response.body = json.str();
    return response;
}

HttpResponse HandleUploadRequest(const HttpRequest& request) {
    HttpResponse response;
    response.SetContentType("text/html");

    std::ostringstream html;
    html << "<!DOCTYPE html>\n";
    html << "<html>\n";
    html << "<head><title>Upload Simulation</title></head>\n";
    html << "<body>\n";
    html << "<h1>Upload Simulation</h1>\n";
    html << "<p>Received " << request.body.length() << " bytes of data.</p>\n";
    html << "<p><strong>Content-Type:</strong> " << request.headers["content-type"] << "</p>\n";
    html << "<p><strong>Content-Length:</strong> " << request.headers["content-length"] << "</p>\n";
    html << "<p><em>This is a simulated upload - the data is not actually saved.</em></p>\n";
    html << "</body>\n";
    html << "</html>\n";

    response.body = html.str();
    return response;
}

// Helper functions
std::string GetCurrentDateTime() {
    time_t now = time(nullptr);
    struct tm timeinfo;
    gmtime_s(&timeinfo, &now);

    char buffer[100];
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S GMT", &timeinfo);
    return std::string(buffer);
}

std::string GetUptime() {
    static DWORD startTime = GetTickCount();
    DWORD uptime = GetTickCount() - startTime;

    DWORD seconds = uptime / 1000;
    DWORD minutes = seconds / 60;
    DWORD hours = minutes / 60;

    seconds %= 60;
    minutes %= 60;

    std::ostringstream oss;
    oss << hours << "h " << minutes << "m " << seconds << "s";
    return oss.str();
}

std::string GetMemoryUsage() {
    PROCESS_MEMORY_COUNTERS pmc;
    if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
        DWORD memoryMB = pmc.WorkingSetSize / (1024 * 1024);
        return std::to_string(memoryMB) + " MB";
    }
    return "Unknown";
}

int GetConnectionCount() {
    // In a real server, this would track active connections
    return 1; // Mock value
}

// 7. Process HTTP request
HttpResponse ProcessRequest(const HttpRequest& request) {
    std::cout << "Processing " << request.method << " " << request.path << std::endl;

    if (request.method == "GET") {
        return HandleGetRequest(request);
    } else if (request.method == "POST") {
        return HandlePostRequest(request);
    } else if (request.method == "HEAD") {
        HttpResponse response = HandleGetRequest(request);
        response.body = ""; // HEAD requests don't include body
        return response;
    } else {
        return CreateErrorResponse(405, "Method not allowed. Use GET, POST, or HEAD.");
    }
}

// 8. Handle client connection
void HandleClient(SOCKET clientSocket, const std::string& clientAddress) {
    char buffer[BUFFER_SIZE];
    int bytesReceived;

    std::cout << "New connection from " << clientAddress << std::endl;

    // Receive request
    std::string requestStr;

    while ((bytesReceived = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0)) > 0) {
        buffer[bytesReceived] = '\0';
        requestStr += buffer;

        // Check if we have the complete request (headers + blank line)
        if (requestStr.find("\r\n\r\n") != std::string::npos) {
            break;
        }
    }

    if (bytesReceived > 0) {
        std::cout << "Received request (" << requestStr.length() << " bytes) from " << clientAddress << std::endl;
        std::cout << "Request preview: " << requestStr.substr(0, std::min(200, (int)requestStr.length())) << "..." << std::endl;

        try {
            // Parse and process request
            HttpRequest request = ParseHttpRequest(requestStr);
            HttpResponse response = ProcessRequest(request);

            // Send response
            std::string responseStr = response.ToString();
            std::cout << "Sending response (" << responseStr.length() << " bytes) to " << clientAddress << std::endl;
            std::cout << "Response status: " << response.statusCode << " " << response.statusText << std::endl;

            if (send(clientSocket, responseStr.c_str(), responseStr.length(), 0) == SOCKET_ERROR) {
                std::cout << "Failed to send response to " << clientAddress << std::endl;
            } else {
                std::cout << "Response sent successfully to " << clientAddress << std::endl;
            }

        } catch (const std::exception& e) {
            std::cout << "Error processing request from " << clientAddress << ": " << e.what() << std::endl;

            HttpResponse errorResponse = CreateErrorResponse(500, "Internal server error");
            std::string errorResponseStr = errorResponse.ToString();
            send(clientSocket, errorResponseStr.c_str(), errorResponseStr.length(), 0);
        }
    } else if (bytesReceived == 0) {
        std::cout << "Client " << clientAddress << " disconnected" << std::endl;
    } else {
        std::cout << "Error receiving from " << clientAddress << std::endl;
    }

    closesocket(clientSocket);
    std::cout << "Connection with " << clientAddress << " closed" << std::endl;
}

// 9. HTTP Server class
class HttpServer {
private:
    SOCKET listenSocket_;
    bool running_;
    int port_;
    std::vector<std::thread> clientThreads_;

public:
    HttpServer() : listenSocket_(INVALID_SOCKET), running_(false), port_(DEFAULT_PORT) {}

    ~HttpServer() {
        Stop();
    }

    bool Start(int port = DEFAULT_PORT) {
        port_ = port;

        std::cout << "Starting HTTP server on port " << port << std::endl;
        std::cout << "Server URL: http://localhost:" << port << std::endl;

        // Create listening socket
        listenSocket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if (listenSocket_ == INVALID_SOCKET) {
            std::cout << "Failed to create listening socket. Error: " << WSAGetLastError() << std::endl;
            return false;
        }

        // Set socket options
        BOOL opt = TRUE;
        setsockopt(listenSocket_, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt));

        // Setup server address
        sockaddr_in serverAddr;
        serverAddr.sin_family = AF_INET;
        serverAddr.sin_addr.s_addr = INADDR_ANY;
        serverAddr.sin_port = htons(port);

        // Bind socket
        if (bind(listenSocket_, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
            std::cout << "Failed to bind socket. Error: " << WSAGetLastError() << std::endl;
            closesocket(listenSocket_);
            return false;
        }

        // Listen for connections
        if (listen(listenSocket_, SOMAXCONN) == SOCKET_ERROR) {
            std::cout << "Failed to listen. Error: " << WSAGetLastError() << std::endl;
            closesocket(listenSocket_);
            return false;
        }

        running_ = true;
        std::cout << "HTTP server started successfully!" << std::endl;
        std::cout << "Press Ctrl+C to stop the server\n" << std::endl;

        // Start accepting connections
        while (running_) {
            sockaddr_in clientAddr;
            int clientAddrSize = sizeof(clientAddr);

            SOCKET clientSocket = accept(listenSocket_, (sockaddr*)&clientAddr, &clientAddrSize);

            if (clientSocket != INVALID_SOCKET) {
                // Get client IP address
                char clientIP[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, INET_ADDRSTRLEN);
                std::string clientAddress = std::string(clientIP) + ":" + std::to_string(ntohs(clientAddr.sin_port));

                // Handle client in a separate thread
                clientThreads_.emplace_back(HandleClient, clientSocket, clientAddress);
            } else {
                int error = WSAGetLastError();
                if (error != WSAEINTR) { // Not interrupted
                    std::cout << "Accept failed. Error: " << error << std::endl;
                }
            }
        }

        // Wait for all client threads to finish
        for (auto& thread : clientThreads_) {
            if (thread.joinable()) {
                thread.join();
            }
        }

        return true;
    }

    void Stop() {
        if (running_) {
            std::cout << "\nStopping HTTP server..." << std::endl;
            running_ = false;

            if (listenSocket_ != INVALID_SOCKET) {
                closesocket(listenSocket_);
                listenSocket_ = INVALID_SOCKET;
            }

            // Wait for all client threads
            for (auto& thread : clientThreads_) {
                if (thread.joinable()) {
                    thread.join();
                }
            }

            clientThreads_.clear();
            std::cout << "HTTP server stopped" << std::endl;
        }
    }
};

// Initialize Winsock
bool InitializeWinsock() {
    WSADATA wsaData;
    int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (result != 0) {
        std::cout << "WSAStartup failed. Error: " << result << std::endl;
        return false;
    }

    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        std::cout << "Winsock 2.2 not available" << std::endl;
        WSACleanup();
        return false;
    }

    std::cout << "Winsock 2.2 initialized successfully" << std::endl;
    return true;
}

// Cleanup Winsock
void CleanupWinsock() {
    WSACleanup();
    std::cout << "Winsock cleaned up" << std::endl;
}

int main() {
    std::cout << "=== C++ Windows HTTP Server Examples ===" << std::endl;
    std::cout << "Demonstrating HTTP server implementation using Winsock\n" << std::endl;

    try {
        // Initialize Winsock
        if (!InitializeWinsock()) {
            return 1;
        }

        // Create and start HTTP server
        HttpServer server;

        // Handle Ctrl+C to gracefully stop server
        SetConsoleCtrlHandler([](DWORD ctrlType) -> BOOL {
            if (ctrlType == CTRL_C_EVENT) {
                std::cout << "\nCtrl+C pressed. Stopping server..." << std::endl;
                return TRUE;
            }
            return FALSE;
        }, TRUE);

        // Start server on port 8080
        if (!server.Start(8080)) {
            std::cout << "Failed to start server" << std::endl;
            CleanupWinsock();
            return 1;
        }

        // Server runs until user presses Ctrl+C or stops automatically

        std::cout << "HTTP server examples completed!" << std::endl;

        // Cleanup Winsock
        CleanupWinsock();

    } catch (const std::exception& e) {
        std::cerr << "Unexpected error: " << e.what() << std::endl;
        CleanupWinsock();
        return 1;
    }

    return 0;
}

Outils

Outils souvent utilisés avec cet exemple

Associé

Collections d’exemples associées

Associé

Dossiers associés

Dossier

Déduire un JSON Schema depuis des exemples et des tableurs

Produisez un brouillon de JSON Schema relisible à partir d'exemples JSON représentatifs ou de lignes XLSX, puis examinez types, caractère obligatoire, valeurs nulles et anomalies avant toute adoption contractuelle.

Dossier

D'une photo à un kit d'images réseaux sociaux prêt pour chaque plateforme

Partez d'une seule photo maître, exportez des recadrages aux bonnes dimensions pour Instagram, TikTok, LinkedIn et X, vérifiez les zones de sécurité des sous-titres, montez des grilles découpées et des collages, et ajoutez des variantes stylisées nommées clairement quand le ton du compte le permet.

Dossier

Contrôles de format des identifiants d'infrastructure réseau

Vérifiez la syntaxe des adresses IPv4 et IPv6, des valeurs CIDR, des adresses MAC, des ARN AWS et des références d'images Docker avant leur traitement, en séparant les preuves de format de l'accessibilité, de la propriété, des droits et de la disponibilité de l'image.

Dossier

D’un article aux brouillons X et LinkedIn : revue factuelle et livraison

Adaptez un article autorisé, vérifiez faits et liens et livrez les brouillons avec un registre de preuves séparé, sans publication.

Accueil
Outils3212
Atelier
Exemples593
Visualisations471
Visionneuses de fichiers103
Dossiers239
Étiquettes333
Images, audio et vidéo657

Outils de traitement, conversion et optimisation d’images, d’audio et de vidéo

Maths, dates et finance647

Calculateurs, outils numériques, logique de dates, statistiques et finance

Design et couleur298

Outils de couleur, mise en page, graphisme, style visuel et assistance design

Texte et rédaction209

Outils de rédaction, nettoyage, formatage, extraction et analyse de texte

Développement et Web193

Utilitaires développeur, réseau, débogage Web et assistants d’automatisation

Conversion et encodage175

Outils de conversion de formats, fichiers, archives, unités et encodages

Lancement d’un quiz de prospection et transmission des contacts
Textes commémoratifs : validation familiale et remise pour impression
Habitudes privées : sauvegarde, restauration et partage vérifié
D’un article aux brouillons X et LinkedIn : revue factuelle et livraison
Revue de cours Markdown interactif et livraison hors ligne

© 2026 Elysia Tools. Tous droits réservés.

DocumentationTarifsÀ proposConditions d'utilisationPolitique de confidentialitéCookiesContact

Development

Generateur de Snippets de Requetes API

Genere du cURL et des snippets dans des langages courants a partir d une URL, methode, en-tetes, query et body

Development

Serveur Mock API

Genere un serveur mock temporaire avec Redis et reponses dynamiques

Networking

Bac à sable de politique BGP AS_PATH

Simule la détection des boucles AS_PATH, les filtres de politique, les attributs et le choix déterministe du meilleur chemin.

Format Conversion

Visualiseur JSON

Visualisez et éditez des données JSON avec des formulaires interactifs et des mises à jour en temps réel

Security

Décodeur JWT

Décoder les tokens JWT

Security

Générateur JWT

Générer des tokens JWT avec des revendications et algorithmes personnalisés

PDF Tools

Remplissage par lot de formulaire PDF

Remplit un modèle de formulaire PDF avec un tableau d'enregistrements et produit un PDF par enregistrement (ZIP) ou un PDF fusionné

Document Tools

Maquette Formulaire PDF Multi-pages

Disposition de formulaire imprimable avec champs, cases et signature

C++

Exemples de Sérialisation Windows C++

Exemples de sérialisation de données Windows C++ incluant la sérialisation/désérialisation JSON et l'analyse XML

Go

Exemples de Réseau Web Go

Exemples de réseau Web Go incluant les requêtes HTTP, les serveurs HTTP et les sockets TCP

C#

Programmation Réseau Windows - Exemples C#

Exemples complets de programmation réseau C# pour plateforme Windows incluant requêtes HTTP, sockets TCP, communication UDP et implémentation serveur web

Documents

Exemples PDF

Exemples PDF generes par les outils du 2026-02-01 au 2026-02-10

Objective-C

Exemples Réseau macOS Objective-C

Exemples réseau macOS Objective-C incluant URLSession, requêtes HTTP, WebSocket et accessibilité réseau

Observabilité

Exemples de Traçage Distribué

Exemples complets de traçage distribué utilisant Jaeger, OpenTelemetry et outils d'observabilité modernes