C++HTTP简易留言板

打印 上一主题 下一主题

主题 1023|帖子 1023|积分 3069

Windows

  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <winsock2.h>
  5. #include <windows.h>
  6. #include <vector>
  7. #include <Ws2tcpip.h>
  8. #include <sstream>
  9. #include <iomanip>
  10. #include <cctype>
  11. #include <ctime>
  12. #include <regex>
  13. #pragma comment(lib, "ws2_32.lib")
  14. const char* commonResponseHeaders = "Content-Type: text/html\r\n";
  15. // URL 解码函数
  16. #include <iostream>
  17. #include <string>
  18. std::string urlDecode(const std::string& str) {
  19.     std::string result;
  20.     for (size_t i = 0; i < str.size(); ++i) {
  21.         if (str[i] == '%' && i + 2 < str.size() && std::isxdigit(str[i + 1]) && std::isxdigit(str[i + 2])) {
  22.             std::string hexCode = str.substr(i + 1, 2);
  23.             char decodedChar = static_cast<char>(std::stoi(hexCode, 0, 16));
  24.             result += decodedChar;
  25.             i += 2;
  26.         }
  27.         else if (str[i] == '+') {
  28.             result += ' ';  // 这里应该是添加空格
  29.         }
  30.         else {
  31.             result += str[i];
  32.         }
  33.     }
  34.     return result;
  35. }
  36. // 过滤 HTML 符号的函数
  37. std::string filterHtmlTags(const std::string& message) {
  38.     std::regex htmlTagsRegex("<[^>]*>");
  39.     return std::regex_replace(message, htmlTagsRegex, "");
  40. }
  41. void handleRequest(SOCKET clientSocket) {
  42.     char buffer[1024];
  43.     int bytesRead = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);  // 确保不会超出缓冲区
  44.     if (bytesRead <= 0) {
  45.         std::cerr << "Error receiving data from client" << std::endl;
  46.         return;
  47.     }
  48.     buffer[bytesRead] = '\0';  // 确保字符串以 null 结尾
  49.     std::string request(buffer);
  50.     // 获取当前日期并构建文件路径
  51.     time_t t = time(NULL);
  52.     std::tm localTime;
  53.     localtime_s(&localTime, &t);
  54.     std::string folderName = "rec_request";
  55.     CreateDirectoryA(folderName.c_str(), NULL);
  56.     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";
  57.     // 获取当前时间并格式化
  58.     char timeBuffer[26];
  59.     ctime_s(timeBuffer, sizeof(timeBuffer), &t);
  60.     std::string timeStr(timeBuffer);
  61.     timeStr.pop_back();  // 去除换行符
  62.     // 打开或创建文件并写入时间和请求
  63.     std::ofstream file(fileName, std::ios::app);
  64.     file << timeStr << std::endl;
  65.     file << std::string(64, '=') << std::endl;
  66.     file << request << std::endl;
  67.     file.close();
  68.     std::cout << "Received request:\n" << request << std::endl;
  69.     std::string method, uri, version;
  70.     size_t firstSpace = request.find(' ');
  71.     size_t secondSpace = request.find(' ', firstSpace + 1);
  72.     if (firstSpace != std::string::npos && secondSpace != std::string::npos) {
  73.         method = request.substr(0, firstSpace);
  74.         uri = request.substr(firstSpace + 1, secondSpace - firstSpace - 1);
  75.         version = request.substr(secondSpace + 1, request.find("\r\n") - secondSpace - 1);
  76.     }
  77.     else {
  78.         std::cerr << "Invalid request" << std::endl;
  79.         return;
  80.     }
  81.     std::cout << "Method: " << method << ", URI: " << uri << ", Version: " << version << std::endl;
  82.     // 处理根路径和 /message_board
  83.     if (uri == "/" || uri == "/message_board") {
  84.         std::string response = "HTTP/1.1 200 OK\r\n";
  85.         response += commonResponseHeaders;
  86.         response += "\r\n";
  87.         response += "<html><style>";
  88.         response += "body { font-family: Arial, sans-serif; background-color: #f0f0f0; }";
  89.         response += "h2 { color: #333; }";
  90.         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); }";
  91.         response += ".message-form { margin-bottom: 20px; }";
  92.         response += ".message { border: 1px solid #ccc; padding: 10px; margin: 10px 0; background-color: #fff; word-wrap: break-word; }";
  93.         response += "input[type='text'] { width: 100%; height: 200px; }";  // 设置输入框高度为 200 像素
  94.         response += "input[type='submit'] { width: 100%; padding: 10px; font-size: 16px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; }";
  95.         response += "input[type='submit']:hover { background-color: #45a049; }";
  96.         response += "</style></head><body>";
  97.         response += "<div class='container'>";
  98.         response += "<h2>留言板</h2>";
  99.         response += "<div class='message-form'><form action='/submit_message' method='post'>";
  100.         response += "留言: <input type='text' name='message' required><br>";
  101.         response += "<input type='submit' value='提交'>";
  102.         response += "</form></div>";
  103.         // 读取并显示留言内容
  104.         std::ifstream logFile("message.txt");  // 更改文件名
  105.         if (logFile.is_open()) {
  106.             std::string line;
  107.             while (std::getline(logFile, line)) {
  108.                 response += "<div class='message'>" + line + "</div>";
  109.             }
  110.             logFile.close();
  111.         }
  112.         response += "<div style='font-size:12px; color:#999; text-align:center;'>Power by Hank Q:1101773014</div>";  // 添加版权信息
  113.         response += "</div></body></html>";
  114.         send(clientSocket, response.c_str(), response.size(), 0);
  115.     }
  116.     else if (uri == "/submit_message" && method == "POST") {
  117.         size_t contentLengthStart = request.find("Content-Length: ");
  118.         if (contentLengthStart == std::string::npos) {
  119.             std::cerr << "Invalid submit message request" << std::endl;
  120.             return;
  121.         }
  122.         size_t contentLengthEnd = request.find("\r\n", contentLengthStart);
  123.         size_t contentLength = std::stoi(request.substr(contentLengthStart + 16, contentLengthEnd - contentLengthStart - 16));
  124.         size_t bodyStart = request.find("\r\n\r\n") + 4;
  125.         std::string body = request.substr(bodyStart, contentLength);
  126.         size_t messageStart = body.find("message=") + 8;
  127.         std::string submittedMessage = urlDecode(body.substr(messageStart));
  128.         // 过滤 HTML 符号
  129.         submittedMessage = filterHtmlTags(submittedMessage);
  130.         // 获取当前时间
  131.         std::time_t t = std::time(nullptr);
  132.         std::tm localTime;
  133.         localtime_s(&localTime, &t);
  134.         std::ostringstream oss;
  135.         oss << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S");
  136.         SOCKADDR_IN clientAddress;
  137.         int clientAddressLength = sizeof(clientAddress);
  138.         if (getpeername(clientSocket, (SOCKADDR*)&clientAddress, &clientAddressLength) == SOCKET_ERROR) {
  139.             std::cerr << "Error getting client IP address" << std::endl;
  140.             return;
  141.         }
  142.         char ipAddressBuffer[INET_ADDRSTRLEN];
  143.         if (inet_ntop(AF_INET, &clientAddress.sin_addr, ipAddressBuffer, INET_ADDRSTRLEN) == NULL) {
  144.             std::cerr << "Error converting IP address" << std::endl;
  145.             return;
  146.         }
  147.         std::string clientIP = std::string(ipAddressBuffer);
  148.         std::ofstream logFile("message.txt", std::ios::app);  // 更改文件名
  149.         logFile << oss.str() << " " << clientIP << ": " << submittedMessage << std::endl;
  150.         logFile.close();
  151.         // 重定向回主页
  152.         std::string response = "HTTP/1.1 303 See Other\r\n";
  153.         response += "Location: /\r\n";
  154.         response += "\r\n";
  155.         send(clientSocket, response.c_str(), response.size(), 0);
  156.     }
  157.     else {
  158.         std::string response = "HTTP/1.1 404 Not Found\r\n";
  159.         response += commonResponseHeaders;
  160.         response += "\r\n";
  161.         response += "<html><body>";
  162.         response += "<h2>404 Not Found</h2>";
  163.         response += "</body></html>";
  164.         send(clientSocket, response.c_str(), response.size(), 0);
  165.     }
  166.     closesocket(clientSocket);
  167. }
  168. int main() {
  169.     WSADATA wsaData;
  170.     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
  171.         std::cerr << "WSAStartup failed" << std::endl;
  172.         return 1;
  173.     }
  174.     SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);
  175.     if (serverSocket == INVALID_SOCKET) {
  176.         std::cerr << "Error creating socket" << std::endl;
  177.         WSACleanup();
  178.         return 1;
  179.     }
  180.     SOCKADDR_IN serverAddress;
  181.     memset(&serverAddress, 0, sizeof(serverAddress));
  182.     serverAddress.sin_family = AF_INET;
  183.     serverAddress.sin_addr.s_addr = INADDR_ANY;
  184.     serverAddress.sin_port = htons(80);
  185.     if (bind(serverSocket, (SOCKADDR*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) {
  186.         std::cerr << "Error binding socket" << std::endl;
  187.         closesocket(serverSocket);
  188.         WSACleanup();
  189.         return 1;
  190.     }
  191.     if (listen(serverSocket, 5) == SOCKET_ERROR) {
  192.         std::cerr << "Error listening on socket" << std::endl;
  193.         closesocket(serverSocket);
  194.         WSACleanup();
  195.         return 1;
  196.     }
  197.     std::cout << "Server is listening on port 80..." << std::endl;
  198.     while (true) {
  199.         SOCKADDR_IN clientAddress;
  200.         int clientAddressLength = sizeof(clientAddress);
  201.         SOCKET clientSocket = accept(serverSocket, (SOCKADDR*)&clientAddress, &clientAddressLength);
  202.         if (clientSocket == INVALID_SOCKET) {
  203.             std::cerr << "Error accepting client connection" << std::endl;
  204.             continue;
  205.         }
  206.         handleRequest(clientSocket);
  207.     }
  208.     closesocket(serverSocket);
  209.     WSACleanup();
  210.     return 0;
  211. }
复制代码
Linux

  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <sys/stat.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <vector>
  10. #include <sstream>
  11. #include <iomanip>
  12. #include <cctype>
  13. #include <ctime>
  14. #include <regex>
  15. #include <codecvt>
  16. // URL 解码函数
  17. std::string urlDecode(const std::string& str) {
  18.     std::string result;
  19.     for (size_t i = 0; i < str.size(); ++i) {
  20.         if (str[i] == '%' && i + 2 < str.size() && std::isxdigit(str[i + 1]) && std::isxdigit(str[i + 2])) {
  21.             std::string hexCode = str.substr(i + 1, 2);
  22.             char decodedChar = static_cast<char>(std::stoi(hexCode, 0, 16));
  23.             result += decodedChar;
  24.             i += 2;
  25.         }
  26.         else if (str[i] == '+') {
  27.             result += ' ';
  28.         }
  29.         else {
  30.             result += str[i];
  31.         }
  32.     }
  33.     return result;
  34. }
  35. // 过滤 HTML 符号的函数
  36. std::string filterHtmlTags(const std::string& message) {
  37.     std::regex htmlTagsRegex("<[^>]*>");
  38.     return std::regex_replace(message, htmlTagsRegex, "");
  39. }
  40. void handleRequest(int clientSocket) {
  41.     char buffer[1024];
  42.     int bytesRead = recv(clientSocket, buffer, sizeof(buffer) - 1, 0);  // 确保不会超出缓冲区
  43.     if (bytesRead <= 0) {
  44.         std::cerr << "Error receiving data from client" << std::endl;
  45.         return;
  46.     }
  47.     buffer[bytesRead] = '\0';  // 确保字符串以 null 结尾
  48.     std::string request(buffer);
  49.     // 获取当前日期并构建文件路径
  50.     time_t t = time(NULL);
  51.     struct tm localTime;
  52.     localtime_r(&t, &localTime);
  53.     std::string folderName = "rec_request";
  54.     mkdir(folderName.c_str(), 0777);
  55.     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";
  56.     // 获取当前时间并格式化
  57.     char timeBuffer[26];
  58.     ctime_r(&t, timeBuffer);
  59.     std::string timeStr(timeBuffer);
  60.     timeStr.pop_back();  // 去除换行符
  61.     // 打开或创建文件并写入时间和请求
  62.     std::ofstream file(fileName, std::ios::app);
  63.     file << timeStr << std::endl;
  64.     file << std::string(64, '=') << std::endl;
  65.     struct sockaddr_in clientAddress;
  66.     socklen_t clientAddressLength = sizeof(clientAddress);
  67.     if (getpeername(clientSocket, (struct sockaddr*)&clientAddress, &clientAddressLength) == -1) {
  68.         std::cerr << "Error getting client IP address" << std::endl;
  69.         return;
  70.     }
  71.     char ipAddressBuffer[INET_ADDRSTRLEN];
  72.     if (inet_ntop(AF_INET, &clientAddress.sin_addr, ipAddressBuffer, INET_ADDRSTRLEN) == NULL) {
  73.         std::cerr << "Error converting IP address" << std::endl;
  74.         return;
  75.     }
  76.     std::string clientIP = std::string(ipAddressBuffer);
  77.     file << "Client IP: " << clientIP << std::endl;
  78.     file << "Request Headers:\n" << request << std::endl;  // 写入请求头
  79.     std::cout << "Received request:\n" << request << std::endl;
  80.     std::string method, uri, version;
  81.     size_t firstSpace = request.find(' ');
  82.     size_t secondSpace = request.find(' ', firstSpace + 1);
  83.     if (firstSpace != std::string::npos && secondSpace != std::string::npos) {
  84.         method = request.substr(0, firstSpace);
  85.         uri = request.substr(firstSpace + 1, secondSpace - firstSpace - 1);
  86.         version = request.substr(secondSpace + 1, request.find("\r\n") - secondSpace - 1);
  87.     }
  88.     else {
  89.         std::cerr << "Invalid request" << std::endl;
  90.         return;
  91.     }
  92.     std::cout << "Method: " << method << ", URI: " << uri << ", Version: " << version << std::endl;
  93.     // 处理根路径和 /message_board
  94.     if (uri == "/" || uri == "/message_board") {
  95.         std::string response = "HTTP/1.1 200 OK\r\n";
  96.         response += "Content-Type: text/html; charset=utf-8\r\n";
  97.         response += "\r\n";
  98.         response += "<html><style>";
  99.         response += "body { font-family: Arial, sans-serif; background-color: #f0f0f0; }";
  100.         response += "h2 { color: #333; }";
  101.         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); }";
  102.         response += ".message-form { margin-bottom: 20px; }";
  103.         response += ".message { border: 1px solid #ccc; padding: 10px; margin: 10px 0; background-color: #fff; word-wrap: break-word; }";
  104.         response += "input[type='text'] { width: 100%; height: 200px; }";
  105.         response += "input[type='submit'] { width: 100%; padding: 10px; font-size: 16px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer; }";
  106.         response += "input[type='submit']:hover { background-color: #45a049; }";
  107.         response += "</style></head><body>";
  108.         response += "<div class='container'>";
  109.         response += "<h2>留言板</h2>";
  110.         response += "<div class='message-form'><form action='/submit_message' method='post'>";
  111.         response += "留言: <input type='text' name='message' required><br>";
  112.         response += "<input type='submit' value='提交'>";
  113.         response += "</form></div>";
  114.         // 读取并显示留言内容
  115.         std::ifstream logFile("message.txt");
  116.         if (logFile.is_open()) {
  117.             std::string line;
  118.             while (std::getline(logFile, line)) {
  119.                 response += "<div class='message'>" + line + "</div>";
  120.             }
  121.             logFile.close();
  122.         }
  123.         response += "<div style='font-size:12px; color:#999; text-align:center;'>Power by Hank Q:1101773014</div>";
  124.         response += "</div></body></html>";
  125.         send(clientSocket, response.c_str(), response.size(), 0);
  126.     }
  127.     else if (uri == "/submit_message" && method == "POST") {
  128.         size_t contentLengthStart = request.find("Content-Length: ");
  129.         if (contentLengthStart == std::string::npos) {
  130.             std::cerr << "Invalid submit message request" << std::endl;
  131.             return;
  132.         }
  133.         size_t contentLengthEnd = request.find("\r\n", contentLengthStart);
  134.         size_t contentLength = std::stoi(request.substr(contentLengthStart + 16, contentLengthEnd - contentLengthStart - 16));
  135.         size_t bodyStart = request.find("\r\n\r\n") + 4;
  136.         std::string body = request.substr(bodyStart, contentLength);
  137.         size_t messageStart = body.find("message=") + 8;
  138.         std::string submittedMessage = urlDecode(body.substr(messageStart));
  139.         // 过滤 HTML 符号
  140.         submittedMessage = filterHtmlTags(submittedMessage);
  141.         // 获取当前时间
  142.         std::time_t t = std::time(nullptr);
  143.         struct tm localTime;
  144.         localtime_r(&t, &localTime);
  145.         std::ostringstream oss;
  146.         oss << std::put_time(&localTime, "%Y-%m-%d %H:%M:%S");
  147.         // 在写入文件的地方进行修改
  148.         std::ofstream logFile("message.txt", std::ios::app);
  149.         std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;  // 创建编码转换器
  150.         // 假设要写入的字符串是 submittedMessage
  151.         std::wstring wideMessage = conv.from_bytes(submittedMessage);  // 转换为宽字符字符串
  152.         logFile << oss.str() << " " << clientIP << ": " << conv.to_bytes(wideMessage) << std::endl;  // 以 utf-8 编码写入
  153.         logFile.close();
  154.         // 重定向回主页
  155.         std::string response = "HTTP/1.1 303 See Other\r\n";
  156.         response += "Location: /\r\n";
  157.         response += "\r\n";
  158.         send(clientSocket, response.c_str(), response.size(), 0);
  159.     }
  160.     else {
  161.         std::string response = "HTTP/1.1 404 Not Found\r\n";
  162.         response += "Content-Type: text/html\r\n";
  163.         response += "\r\n";
  164.         response += "<html><body>";
  165.         response += "<h2>404 Not Found</h2>";
  166.         response += "</body></html>";
  167.         send(clientSocket, response.c_str(), response.size(), 0);
  168.     }
  169.     close(clientSocket);
  170. }
  171. int main() {
  172.     int serverSocket = socket(AF_INET, SOCK_STREAM, 0);
  173.     if (serverSocket == -1) {
  174.         std::cerr << "Error creating socket" << std::endl;
  175.         return 1;
  176.     }
  177.     struct sockaddr_in serverAddress;
  178.     memset(&serverAddress, 0, sizeof(serverAddress));
  179.     serverAddress.sin_family = AF_INET;
  180.     serverAddress.sin_addr.s_addr = INADDR_ANY;
  181.     serverAddress.sin_port = htons(80);
  182.     if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1) {
  183.         std::cerr << "Error binding socket" << std::endl;
  184.         close(serverSocket);
  185.         return 1;
  186.     }
  187.     if (listen(serverSocket, 5) == -1) {
  188.         std::cerr << "Error listening on socket" << std::endl;
  189.         close(serverSocket);
  190.         return 1;
  191.     }
  192.     std::cout << "Server is listening on port 80..." << std::endl;
  193.     while (true) {
  194.         struct sockaddr_in clientAddress;
  195.         socklen_t clientAddressLength = sizeof(clientAddress);
  196.         int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientAddressLength);
  197.         if (clientSocket == -1) {
  198.             std::cerr << "Error accepting client connection" << std::endl;
  199.             continue;
  200.         }
  201.         handleRequest(clientSocket);
  202.     }
  203.     close(serverSocket);
  204.     return 0;
  205. }
复制代码
Linux开机启动配置文件
  1. # /etc/systemd/system vi http-server.service
  2. [Unit]
  3. Description=My HTTP Server
  4. After=network.target
  5. [Service]
  6. ExecStart=/root/projects/留言板Linux/bin/x64/Release/留言板Linux.out
  7. WorkingDirectory=/root/projects/留言板Linux/bin/x64/Release
  8. User=root
  9. Group=root
  10. Restart=always
  11. [Install]
  12. WantedBy=multi-user.target
复制代码
启动代码
  1. sudo systemctl daemon-reload
  2. sudo systemctl enable http-server.service
  3. sudo systemctl start http-server.service
  4. systemctl status http-server.service # 看到 active (running) 就成功了
复制代码

http://1.92.93.88/

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

科技颠覆者

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表