rkey

rkey

Write an HTTP server in C++.

Without using any advanced frameworks, you can implement a simple HTTP server using the C++ standard library and some system calls. Below is a basic example that demonstrates how to create a simple HTTP server using headers like <iostream> and <sys/socket.h> from the C++ standard library to receive requests and return a simple response. This HTTP server only handles one network request; if you want to continuously process requests, you can add a loop to keep handling requests.

Example: Simple HTTP Server#

This example will use raw socket programming to create a simple HTTP server that listens on a port and handles incoming connections.

#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>

int main() {
    // Create socket
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        std::cerr << "Error creating socket" << std::endl;
        return 1;
    }

    // Set socket options to allow address reuse
    int opt = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        std::cerr << "Error setting socket options" << std::endl;
        return 1;
    }

    // Server address structure
    struct sockaddr_in address;
    int addrlen = sizeof(address);
    memset(&address, 0, sizeof(address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(8080);

    // Bind socket to address
    if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
        std::cerr << "Error binding socket" << std::endl;
        return 1;
    }

    // Listen for connections
    if (listen(server_fd, 3) < 0) {
        std::cerr << "Error listening on socket" << std::endl;
        return 1;
    }

    std::cout << "Server listening on port 8080" << std::endl;

    // Accept connection
    int new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
    if (new_socket < 0) {
        std::cerr << "Error accepting connection" << std::endl;
        return 1;
    }

    // Receive request
    char buffer[1024] = {0};
    read(new_socket, buffer, 1024);
    std::cout << "Request: " << buffer << std::endl;

    // Send response
    const std::string response = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<html><body><h1>Hello, World!</h1></body></html>";
    send(new_socket, response.c_str(), response.size(), 0);

    // Close socket
    close(new_socket);
    close(server_fd);

    return 0;
}

Code Explanation#

  1. Create Socket:

    • Use the socket function to create a TCP socket.
  2. Set Socket Options:

    • Use the setsockopt function to set SO_REUSEADDR and SO_REUSEPORT options to allow address and port reuse.
  3. Server Address Structure:

    • Use the sockaddr_in structure to store the server's address information.
    • INADDR_ANY means the server can accept connections from any IP address.
  4. Bind Socket:

    • Use the bind function to bind the socket to the specified address and port.
  5. Listen for Connections:

    • Use the listen function to start listening for connections, with the parameter 3 indicating the maximum length of the connection queue.
  6. Accept Connection:

    • Use the accept function to accept incoming connections.
  7. Receive Request:

    • Use the read function to read request data from the connection and print it to standard output.
  8. Send Response:

    • Construct a simple HTTP response string and use the send function to send the response.
  9. Close Socket:

    • Use the close function to close the connection and listening socket.

Compile and Run#

Save the above code as http_server.cpp, then compile and run using g++:

g++ -o http_server http_server.cpp
./http_server

Test#

Open a browser or use curl to test your server:

curl http://localhost:8080

You should see the returned "Hello, World!".

Notes#

  • This example is for demonstration purposes only; actual applications may need to handle more edge cases, such as multi-threading or asynchronous handling of multiple connections, parsing HTTP requests, and handling different HTTP methods and paths.
  • To simplify the example, HTTP request headers and body separation are not handled here; actual applications may require more complex parsing logic.
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.