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#
-
Create Socket:
- Use the
socket
function to create a TCP socket.
- Use the
-
Set Socket Options:
- Use the
setsockopt
function to setSO_REUSEADDR
andSO_REUSEPORT
options to allow address and port reuse.
- Use the
-
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.
- Use the
-
Bind Socket:
- Use the
bind
function to bind the socket to the specified address and port.
- Use the
-
Listen for Connections:
- Use the
listen
function to start listening for connections, with the parameter3
indicating the maximum length of the connection queue.
- Use the
-
Accept Connection:
- Use the
accept
function to accept incoming connections.
- Use the
-
Receive Request:
- Use the
read
function to read request data from the connection and print it to standard output.
- Use the
-
Send Response:
- Construct a simple HTTP response string and use the
send
function to send the response.
- Construct a simple HTTP response string and use the
-
Close Socket:
- Use the
close
function to close the connection and listening socket.
- Use the
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.