Windows
#include <iostream>
#include <fstream>
#include <string>
#include <winsock2.h>
#include <windows.h>
#include <vector>
#include <Ws2tcpip.h>
#include <sstream>
#include <iomanip>
#include <cctype>
#include <ctime>
#include <regex>
#pragma comment(lib, "ws2_32.lib")
const char* commonResponseHeaders = "Content-Type: text/html\r\n";
// URL 解码函数
#include <iostream>
#include <string>
std::string urlDecode(const std::string& str) {
std::string result;
for (size_t i = 0; i < str.size(); ++i) {
if (str[i] == '%' && i + 2 < str.size() && std::isxdigit(str[i + 1]) && std::isxdigit(str[i + 2])) {
std::string hexCode = str.substr(i + 1, 2);
char decodedChar = static_cast<char>(std::stoi(hexCode, 0, 16));
result += decodedChar;
i += 2;
}
else if (str[i] == '+') {
result += ' '; // 这里应该是添加空格
}
else {
result += str[i];
}
}
return result;
}
// 过滤 HTML 符号的函数
std::string filterHtmlTags(const std::string& message) {
std::regex htmlTagsRegex("<[^>]*>");
return std::regex_replace(message, htmlTagsRegex, "");
}
void handleRequest(SOCKET clientSocket) {
char buffer[1024];
int bytesRead = recv(clientSocket, buffer, sizeof(buffer) - 1, 0); // 确保不会超出缓冲区
if (bytesRead <= 0) {
std::cerr << "Error receiving data from client" << std::endl;
return;
}
buffer[bytesRead] = '\0'; // 确保字符串以 null 结尾
std::string request(buffer);
// 获取当前日期并构建文件路径
time_t t = time(NULL);
std::tm localTime;
localtime_s(&localTime, &t);
std::string folderName = "rec_request";
CreateDirectoryA(folderName.c_str(), NULL);
std::string fileName = folderName + "/" + std::to_string(1900 + localTime.tm_year) + "-" + std::to_string(1 + localTime.tm_mon) + "-" + std::to_string(localTime.tm_mday) + ".log";
// 获取当前时间并格式化
char timeBuffer[26];
ctime_s(timeBuffer, sizeof(timeBuffer), &t);
std::string timeStr(timeBuffer);
timeStr.pop_back(); // 去除换行符
// 打开或创建文件并写入时间和请求
std::ofstream file(fileName, std::ios::app);
file << timeStr << std::endl;
file << std::string(64, '=') << std::endl;
file << request << std::endl;
file.close();
std::cout << "Received request:\n" << request << std::endl;
std::string method, uri, version;
size_t firstSpace = request.find(' ');
size_t secondSpace = request.find(' ', firstSpace + 1);
if (firstSpace != std::string::npos && secondSpace != std::string::npos) {
method = request.substr(0, firstSpace);
uri = request.substr(firstSpace + 1, secondSpace - firstSpace - 1);
version = request.substr(secondSpace + 1, request.find("\r\n") - secondSpace - 1);
}
else {
std::cerr << "Invalid request" << std::endl;
return;
}
std::cout << "Method: " << method << ", URI: " << uri << ", Version: " << version << std::endl;
// 处理根路径和 /message_board
if (uri == "/" || uri == "/message_board") {
std::string response = "HTTP/1.1 200 OK\r\n";
response += commonResponseHeaders;
response += "\r\n";
response += "<html><style>";
response += "body { font-family: Arial, sans-serif; background-color: #f0f0f0; }";
response += "h2 { color: #333; }";
response += ".container { max-width: 800px; margin: 0 auto; padding: 20px; background-color: #fff; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); }";
response += ".message-form { margin-bottom: 20px; }";
response += ".message { border: 1px solid #ccc; padding: 10px; margin: 10px 0; background-color: #fff; word-wrap: break-word; }";
response += "input[type='text'] { width: 100%; height: 200px; }"; // 设置输入框高度为 200 像素
response += "input[type='submit'] { width: 100%; padding: 10px; font-size: 16px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; }";
response += "input[type='submit']:hover { background-color: #45a049; }";
response += "</style></head><body>";
response += "<div class='container'>";
response += "<h2>留言板</h2>";
response += "<div class='message-form'><form action='/submit_message' method='post'>";
response += "留言: <input type='text' name='message' required><br>";
response += "<input type='submit' value='提交'>";
response += "</form></div>";
// 读取并显示留言内容
std::ifstream logFile("message.txt"); // 更改文件名
if (logFile.is_open()) {
std::string line;
while (std::getline(logFile, line)) {
response += "<div class='message'>" + line + "</div>";
}
logFile.close();
}
response += "<div style='font-size:12px; color:#999; text-align:center;'>Power by Hank Q:1101773014</div>"; // 添加版权信息
response += "</div></body></html>";
send(clientSocket, response.c_str(), response.size(), 0);
}
else if (uri == "/submit_message" && method == "POST") {
size_t contentLengthStart = request.find("Content-Length: ");
if (contentLengthStart == std::string::npos) {
std::cerr << "Invalid submit message request" << std::endl;
return;
}
size_t contentLengthEnd = request.find("\r\n", contentLengthStart);
size_t contentLength = std::stoi(request.substr(contentLengthStart + 16, contentLengthEnd - contentLengthStart - 16));
size_t bodyStart = request.find("\r\n\r\n") + 4;
std::string body = request.substr(bodyStart, contentLength);
size_t messageStart = body.find("message=") + 8;
std::string submittedMessage = urlDecode(body.substr(messageStart));
// 过滤 HTML 符号
submittedMessage = filterHtmlTags(submittedMessage);
// 获取当前时间
std::time_t t = std::time(nullptr);
std::tm localTime;
localtime_s(&localTime, &t);
std::ostringstream oss;
oss << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S");
SOCKADDR_IN clientAddress;
int clientAddressLength = sizeof(clientAddress);
if (getpeername(clientSocket, (SOCKADDR*)&clientAddress, &clientAddressLength) == SOCKET_ERROR) {
std::cerr << "Error getting client IP address" << std::endl;
return;
}
char ipAddressBuffer[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &clientAddress.sin_addr, ipAddressBuffer, INET_ADDRSTRLEN) == NULL) {
std::cerr << "Error converting IP address" << std::endl;
return;
}
std::string clientIP = std::string(ipAddressBuffer);
std::ofstream logFile("message.txt", std::ios::app); // 更改文件名
logFile << oss.str() << " " << clientIP << ": " << submittedMessage << std::endl;
logFile.close();
// 重定向回主页
std::string response = "HTTP/1.1 303 See Other\r\n";
response += "Location: /\r\n";
response += "\r\n";
send(clientSocket, response.c_str(), response.size(), 0);
}
else {
std::string response = "HTTP/1.1 404 Not Found\r\n";
response += commonResponseHeaders;
response += "\r\n";
response += "<html><body>";
response += "<h2>404 Not Found</h2>";
response += "</body></html>";
send(clientSocket, response.c_str(), response.size(), 0);
}
closesocket(clientSocket);
}
int main() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "WSAStartup failed" << std::endl;
return 1;
}
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET) {
std::cerr << "Error creating socket" << std::endl;
WSACleanup();
return 1;
}
SOCKADDR_IN serverAddress;
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = INADDR_ANY;
serverAddress.sin_port = htons(80);
if (bind(serverSocket, (SOCKADDR*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) {
std::cerr << "Error binding socket" << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
if (listen(serverSocket, 5) == SOCKET_ERROR) {
std::cerr << "Error listening on socket" << std::endl;
closesocket(serverSocket);
WSACleanup();
return 1;
}
std::cout << "Server is listening on port 80..." << std::endl;
while (true) {
SOCKADDR_IN clientAddress;
int clientAddressLength = sizeof(clientAddress);
SOCKET clientSocket = accept(serverSocket, (SOCKADDR*)&clientAddress, &clientAddressLength);
if (clientSocket == INVALID_SOCKET) {
std::cerr << "Error accepting client connection" << std::endl;
continue;
}
handleRequest(clientSocket);
}
closesocket(serverSocket);
WSACleanup();
return 0;
}
Linux
#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <vector>
#include <sstream>
#include <iomanip>
#include <cctype>
#include <ctime>
#include <regex>
#include <codecvt>
// URL 解码函数
std::string urlDecode(const std::string& str) {
std::string result;
for (size_t i = 0; i < str.size(); ++i) {
if (str[i] == '%' && i + 2 < str.size() && std::isxdigit(str[i + 1]) && std::isxdigit(str[i + 2])) {
std::string hexCode = str.substr(i + 1, 2);
char decodedChar = static_cast<char>(std::stoi(hexCode, 0, 16));
result += decodedChar;
i += 2;
}
else if (str[i] == '+') {
result += ' ';
}
else {
result += str[i];
}
}
return result;
}
// 过滤 HTML 符号的函数
std::string filterHtmlTags(const std::string& message) {
std::regex htmlTagsRegex("<[^>]*>");
return std::regex_replace(message, htmlTagsRegex, "");
}
void handleRequest(int clientSocket) {
char buffer[1024];
int bytesRead = recv(clientSocket, buffer, sizeof(buffer) - 1, 0); // 确保不会超出缓冲区
if (bytesRead <= 0) {
std::cerr << "Error receiving data from client" << std::endl;
return;
}
buffer[bytesRead] = '\0'; // 确保字符串以 null 结尾
std::string request(buffer);
// 获取当前日期并构建文件路径
time_t t = time(NULL);
struct tm localTime;
localtime_r(&t, &localTime);
std::string folderName = "rec_request";
mkdir(folderName.c_str(), 0777);
std::string fileName = folderName + "/" + std::to_string(1900 + localTime.tm_year) + "-" + std::to_string(1 + localTime.tm_mon) + "-" + std::to_string(localTime.tm_mday) + ".log";
// 获取当前时间并格式化
char timeBuffer[26];
ctime_r(&t, timeBuffer);
std::string timeStr(timeBuffer);
timeStr.pop_back(); // 去除换行符
// 打开或创建文件并写入时间和请求
std::ofstream file(fileName, std::ios::app);
file << timeStr << std::endl;
file << std::string(64, '=') << std::endl;
struct sockaddr_in clientAddress;
socklen_t clientAddressLength = sizeof(clientAddress);
if (getpeername(clientSocket, (struct sockaddr*)&clientAddress, &clientAddressLength) == -1) {
std::cerr << "Error getting client IP address" << std::endl;
return;
}
char ipAddressBuffer[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &clientAddress.sin_addr, ipAddressBuffer, INET_ADDRSTRLEN) == NULL) {
std::cerr << "Error converting IP address" << std::endl;
return;
}
std::string clientIP = std::string(ipAddressBuffer);
file << "Client IP: " << clientIP << std::endl;
file << "Request Headers:\n" << request << std::endl; // 写入请求头
std::cout << "Received request:\n" << request << std::endl;
std::string method, uri, version;
size_t firstSpace = request.find(' ');
size_t secondSpace = request.find(' ', firstSpace + 1);
if (firstSpace != std::string::npos && secondSpace != std::string::npos) {
method = request.substr(0, firstSpace);
uri = request.substr(firstSpace + 1, secondSpace - firstSpace - 1);
version = request.substr(secondSpace + 1, request.find("\r\n") - secondSpace - 1);
}
else {
std::cerr << "Invalid request" << std::endl;
return;
}
std::cout << "Method: " << method << ", URI: " << uri << ", Version: " << version << std::endl;
// 处理根路径和 /message_board
if (uri == "/" || uri == "/message_board") {
std::string response = "HTTP/1.1 200 OK\r\n";
response += "Content-Type: text/html; charset=utf-8\r\n";
response += "\r\n";
response += "<html><style>";
response += "body { font-family: Arial, sans-serif; background-color: #f0f0f0; }";
response += "h2 { color: #333; }";
response += ".container { max-width: 800px; margin: 0 auto; padding: 20px; background-color: #fff; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); }";
response += ".message-form { margin-bottom: 20px; }";
response += ".message { border: 1px solid #ccc; padding: 10px; margin: 10px 0; background-color: #fff; word-wrap: break-word; }";
response += "input[type='text'] { width: 100%; height: 200px; }";
response += "input[type='submit'] { width: 100%; padding: 10px; font-size: 16px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; }";
response += "input[type='submit']:hover { background-color: #45a049; }";
response += "</style></head><body>";
response += "<div class='container'>";
response += "<h2>留言板</h2>";
response += "<div class='message-form'><form action='/submit_message' method='post'>";
response += "留言: <input type='text' name='message' required><br>";
response += "<input type='submit' value='提交'>";
response += "</form></div>";
// 读取并显示留言内容
std::ifstream logFile("message.txt");
if (logFile.is_open()) {
std::string line;
while (std::getline(logFile, line)) {
response += "<div class='message'>" + line + "</div>";
}
logFile.close();
}
response += "<div style='font-size:12px; color:#999; text-align:center;'>Power by Hank Q:1101773014</div>";
response += "</div></body></html>";
send(clientSocket, response.c_str(), response.size(), 0);
}
else if (uri == "/submit_message" && method == "POST") {
size_t contentLengthStart = request.find("Content-Length: ");
if (contentLengthStart == std::string::npos) {
std::cerr << "Invalid submit message request" << std::endl;
return;
}
size_t contentLengthEnd = request.find("\r\n", contentLengthStart);
size_t contentLength = std::stoi(request.substr(contentLengthStart + 16, contentLengthEnd - contentLengthStart - 16));
size_t bodyStart = request.find("\r\n\r\n") + 4;
std::string body = request.substr(bodyStart, contentLength);
size_t messageStart = body.find("message=") + 8;
std::string submittedMessage = urlDecode(body.substr(messageStart));
// 过滤 HTML 符号
submittedMessage = filterHtmlTags(submittedMessage);
// 获取当前时间
std::time_t t = std::time(nullptr);
struct tm localTime;
localtime_r(&t, &localTime);
std::ostringstream oss;
oss << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S");
// 在写入文件的地方进行修改
std::ofstream logFile("message.txt", std::ios::app);
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv; // 创建编码转换器
// 假设要写入的字符串是 submittedMessage
std::wstring wideMessage = conv.from_bytes(submittedMessage); // 转换为宽字符字符串
logFile << oss.str() << " " << clientIP << ": " << conv.to_bytes(wideMessage) << std::endl; // 以 utf-8 编码写入
logFile.close();
// 重定向回主页
std::string response = "HTTP/1.1 303 See Other\r\n";
response += "Location: /\r\n";
response += "\r\n";
send(clientSocket, response.c_str(), response.size(), 0);
}
else {
std::string response = "HTTP/1.1 404 Not Found\r\n";
response += "Content-Type: text/html\r\n";
response += "\r\n";
response += "<html><body>";
response += "<h2>404 Not Found</h2>";
response += "</body></html>";
send(clientSocket, response.c_str(), response.size(), 0);
}
close(clientSocket);
}
int main() {
int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == -1) {
std::cerr << "Error creating socket" << std::endl;
return 1;
}
struct sockaddr_in serverAddress;
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = INADDR_ANY;
serverAddress.sin_port = htons(80);
if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) {
std::cerr << "Error binding socket" << std::endl;
close(serverSocket);
return 1;
}
if (listen(serverSocket, 5) == -1) {
std::cerr << "Error listening on socket" << std::endl;
close(serverSocket);
return 1;
}
std::cout << "Server is listening on port 80..." << std::endl;
while (true) {
struct sockaddr_in clientAddress;
socklen_t clientAddressLength = sizeof(clientAddress);
int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientAddressLength);
if (clientSocket == -1) {
std::cerr << "Error accepting client connection" << std::endl;
continue;
}
handleRequest(clientSocket);
}
close(serverSocket);
return 0;
}
Linux开机启动配置文件
# /etc/systemd/system vi http-server.service
[Unit]
Description=My HTTP Server
After=network.target
[Service]
ExecStart=/root/projects/留言板Linux/bin/x64/Release/留言板Linux.out
WorkingDirectory=/root/projects/留言板Linux/bin/x64/Release
User=root
Group=root
Restart=always
[Install]
WantedBy=multi-user.target
启动代码
sudo systemctl daemon-reload
sudo systemctl enable http-server.service
sudo systemctl start http-server.service
systemctl status http-server.service # 看到 active (running) 就成功了
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » C++HTTP简易留言板
发表评论 取消回复