Files
webserverle_cpp_win/webserver.cpp
2026-02-25 17:10:36 +01:00

208 lines
7.0 KiB
C++

#include <iostream>
#include <string>
#include <sstream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
const int PORT = 8089;
std::string getHtmlPage(const std::string& path) {
if (path == "/" || path == "/index") {
return R"(<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>C++ Webserver</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: 'Segoe UI', sans-serif;
background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
color: #eee;
}
.card {
background: rgba(255,255,255,0.08);
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.15);
border-radius: 20px;
padding: 50px 60px;
max-width: 600px;
text-align: center;
box-shadow: 0 20px 60px rgba(0,0,0,0.4);
}
.badge {
background: #e94560;
color: white;
padding: 6px 16px;
border-radius: 20px;
font-size: 0.8em;
letter-spacing: 1px;
text-transform: uppercase;
display: inline-block;
margin-bottom: 20px;
}
h1 { font-size: 2.5em; margin-bottom: 15px; }
p { color: rgba(255,255,255,0.7); line-height: 1.7; margin-bottom: 25px; }
.links a {
display: inline-block;
margin: 8px;
padding: 12px 28px;
background: #e94560;
color: white;
text-decoration: none;
border-radius: 10px;
transition: transform 0.2s, background 0.2s;
}
.links a:hover { transform: translateY(-2px); background: #c73652; }
.links a.secondary {
background: rgba(255,255,255,0.1);
border: 1px solid rgba(255,255,255,0.2);
}
.links a.secondary:hover { background: rgba(255,255,255,0.2); }
code {
background: rgba(0,0,0,0.3);
padding: 3px 8px;
border-radius: 5px;
font-size: 0.9em;
color: #7ec8e3;
}
</style>
</head>
<body>
<div class="card">
<div class="badge">C++ HTTP Server</div>
<h1>&#127760; Hallo, Welt!</h1>
<p>
Dieser Webserver wurde komplett in <strong>reinem C++</strong> geschrieben &mdash;
ohne externe Bibliotheken. Er nutzt direkt die
<code>POSIX Socket API</code> des Betriebssystems.
</p>
<div class="links">
<a href="/">&#127968; Startseite</a>
<a href="/info" class="secondary">&#8505;&#65039; Server-Info</a>
<a href="/zeit" class="secondary">&#128336; Uhrzeit</a>
</div>
</div>
</body>
</html>)";
} else if (path == "/info") {
return R"(<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Server Info</title>
<style>
body { font-family: monospace; background: #0d1117; color: #c9d1d9; padding: 40px; }
h1 { color: #58a6ff; }
table { border-collapse: collapse; margin-top: 20px; }
td, th { padding: 10px 20px; border: 1px solid #30363d; }
th { background: #161b22; color: #58a6ff; }
a { color: #58a6ff; }
</style>
</head>
<body>
<h1>&#128295; Server-Informationen</h1>
<table>
<tr><th>Eigenschaft</th><th>Wert</th></tr>
<tr><td>Sprache</td><td>C++ (ISO C++17)</td></tr>
<tr><td>Bibliotheken</td><td>Nur POSIX Standard (sys/socket.h)</td></tr>
<tr><td>Port</td><td>8080</td></tr>
<tr><td>Protokoll</td><td>HTTP/1.0</td></tr>
<tr><td>Plattform</td><td>Linux</td></tr>
</table>
<p style="margin-top:20px"><a href="/">&#8592; Zur&uuml;ck</a></p>
</body>
</html>)";
} else if (path == "/zeit") {
time_t now = time(nullptr);
std::string zeit = std::string(ctime(&now));
return "<!DOCTYPE html><html lang='de'><head><meta charset='UTF-8'><title>Zeit</title>"
"<style>body{font-family:sans-serif;background:#0d1117;color:#c9d1d9;padding:40px;}"
"h1{color:#58a6ff;} a{color:#58a6ff;}</style></head><body>"
"<h1>&#128336; Aktuelle Serverzeit</h1><p style='font-size:1.5em'>" + zeit + "</p>"
"<p><a href='/'>&#8592; Zur&uuml;ck</a></p></body></html>";
}
return R"(<!DOCTYPE html>
<html lang="de"><head><meta charset="UTF-8"><title>404</title>
<style>body{font-family:sans-serif;background:#0d1117;color:#c9d1d9;
text-align:center;padding:80px;}h1{font-size:5em;color:#e94560;}
a{color:#58a6ff;}</style></head>
<body><h1>404</h1><p>Seite nicht gefunden.</p><p><a href="/">Startseite</a></p>
</body></html>)";
}
std::string buildResponse(const std::string& path) {
std::string body = getHtmlPage(path);
std::string status = (path == "/" || path == "/info" || path == "/zeit")
? "200 OK" : "404 Not Found";
std::ostringstream response;
response << "HTTP/1.0 " << status << "\r\n"
<< "Content-Type: text/html; charset=UTF-8\r\n"
<< "Content-Length: " << body.size() << "\r\n"
<< "Connection: close\r\n"
<< "\r\n"
<< body;
return response.str();
}
int main() {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) { std::cerr << "Socket-Fehler\n"; return 1; }
int opt = 1;
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
sockaddr_in address{};
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(server_fd, (sockaddr*)&address, sizeof(address)) < 0) {
std::cerr << "Bind-Fehler\n"; return 1;
}
if (listen(server_fd, 10) < 0) {
std::cerr << "Listen-Fehler\n"; return 1;
}
std::cout << "Server laeuft auf http://localhost:" << PORT << "\n";
std::cout << "Seiten: / /info /zeit\n";
std::cout << "Beenden mit Ctrl+C\n\n";
while (true) {
int client_fd = accept(server_fd, nullptr, nullptr);
if (client_fd < 0) continue;
char buffer[4096] = {};
read(client_fd, buffer, sizeof(buffer) - 1);
// HTTP-Anfrage parsen: "GET /path HTTP/1.x"
std::string request(buffer);
std::string path = "/";
size_t start = request.find(' ');
if (start != std::string::npos) {
size_t end = request.find(' ', start + 1);
if (end != std::string::npos)
path = request.substr(start + 1, end - start - 1);
}
std::cout << "Anfrage: " << path << "\n";
std::string response = buildResponse(path);
send(client_fd, response.c_str(), response.size(), 0);
close(client_fd);
}
close(server_fd);
return 0;
}