一、C++Web服务器(核心代码WebServer.cpp)
要实现一个简单的C++Web服务器,支持GET和POST请求,同时能够提供静态文件(如JavaScript、CSS和图片文件)。
#include <iostream> #include <string> #include <sstream> #include <fstream> #include <unordered_map> #include <netinet/in.h> #include <unistd.h> #include <sys/stat.h> using namespace std; #define PORT 8080 // 端口号 #define BUFFER_SIZE 4096 // 缓冲区大小 //根据文件拓展名返回适当的Content-Type std::string getContentType(const std::string &path){ if(path.ends_with(".html")) return "text/html"; if(path.ends_with(".css")) return "text/css"; if(path.ends_with(".js")) return "application/javascript"; if(path.ends_with(".png")) return "image/png"; if(path.ends_with(".jpg")) return "image/jpeg"; if(path.ends_with(".jpeg")) return "image/jpeg"; if(path.ends_with(".gif")) return "image/gif"; return "text/plain"; } //读取静态文件 std::string readFile(const std::string &path){ //创建一个输入文件流对象,以二进制模式打开指定路径的文件 std::ifstream file(path,std::ios::binary); //检查文件是否成功打开 if(!file.is_open()){ perror("file open failed"); //如果打开失败返回空字符串 return ""; } //创建一个输出字符串流对象,用于将文件内容读取到字符串 std::ostringstream ss; //使用输出字符串流对象的rdbuf()将文件内容读取到字符串中 //这实际上是将文件流中的所有字节复制到字符串流的缓冲区中 ss<<file.rdbuf(); //将字符串流的内容转换为std::string并返回 return ss.str(); } //判断文件是否存在 bool fileExists(const std::string &path){ struct stat buffer; return stat(path.c_str(), &buffer)==0; } int main() { // 创建套接字 int server_fd, new_socket; // 地址结构体 struct sockaddr_in address; int opt=1; // 设置套接字选项 int addlen = sizeof(address);// 地址结构体长度 char buffer[BUFFER_SIZE] = {0}; // 缓冲区 if ((server_fd = socket(AF_INET, SOCK_STREAM, 0))==0){ perror("socket failed"); exit(EXIT_FAILURE); } //设置端口复用 //如果你不是用SO_REUSEADDR,服务器程序关闭后,可能会出现“Address already in use” 错误 //尤其是当你尝试在同一个端口上重新启动服务器时,这是因为TCP连接可能会保持TIME_WAIT的状态一段时间 //而SO_REUSEADDR允许套接字在这种状态下重新绑定到另一个端口 if(setsoocketopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))){ perror("setsoocketopt failed"); exit(EXIT_FAILURE); } //配置服务器地址 addrss.sin_family = AF_INET; addrss.sin_addr.s_addr = INADDR_ANY; addrss.sin_port = htons(PORT); //绑定套接字 if(bind(server_fd, (struct sockaddr *)&address, addlen)<0){ perror("bind failed"); exit(EXIT_FAILURE); } //监听请求 if(listen(server_fd, 3)<0){ perror("listen failed"); exit(EXIT_FAILURE); } cout<<"WebServer is running on port"<<PORT<<"....\n"; while(true) { //接受客户端连接 if((new_socket=accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addlen))<0){ perror("accept failed"); exit(EXIT_FAILURE); } //读取客户端请求 read(new_socket, buffer, BUFFER_SIZE); cout<<"Request received :\n"<<buffer<<endl; //解析Http请求 //这段代码是解析Http请求中提取 请求方法、路径和Http版本。如下: //第一次提取method,得到:GET //第二次提取path,得到:/index.html //第三次提取version,得到:HTTP/1.1 std::istringstream request(buffer); std::string method , path , version; request>>method>>path>>version; //默认首页 if(path=="/") { path="/index.html"; } //构建文件路径 std::string filePath ="."+path; //处理GET请求 if(method=="GET"){ if(fileExists(filePath)){//文件存在 std::string content = readFile(filePath);//读取文件内容 std::string contentType = getContentType(filePath);//获取文件类型 std::ostringstream response; // 构建响应 response<<"HTTP/1.1 200 OK\r\n" <<"Content-Type:"<<contentType<<"\r\n" <<"Content-Length:"<<content.length()<<"\r\n" <<"\r\n" <<content;//响应头和响应体 response<<content; //发送响应 send(new_socket, response.str().c_str(), response.str().length(), 0); }else{ //404 NOT FOUND std::string notFound="HTTP/1.1 404 Not Found\r\n\r\n404 Not Found"; send(new_socket, notFound.c_str(), notFound.length(), 0); } } else if(method=="POST"){//处理POST请求 //简单的响应客户端的POST请求(可以根据需要解析POST请求) std::string response="HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nPOST request"; send(new_socket, response.c_str(), response.length(), 0); }else{ //405 METHOD NOT ALLOWED std::string notAllowed="HTTP/1.1 405 Method Not Allowed\r\n\r\n405 Method Not Allowed"; send(new_socket, notAllowed.c_str(), notAllowed.length(), 0); } //关闭连接 close(new_socket); } //释放资源,关闭服务器套接字 close(server_fd); return 0; }
二、静态文件结构
- 确保你的HTML、CSS、JS和图片文件都存放在与可执行程序相同的目录下或适当的子目录中,例如:
./index.html ./style.css ./script.js ./images/example.jjpg
假设HTL文件是这样的:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>这是一个简单的WebServer</title> <style> body{ font-family: Arial,sans-serif; background-color: #f4f4f9; color: #333; margin: 0; padding: 0; } header{ background-color: #4CAF50; color: white; padding: 10px 0; } h1{ margin: 0; } p{ font-size: 1.2em; margin: 20px auto; width: 80%; } footer{ position: fixed; bottom: 0; width: 100%; background-color: #4CAF50; color: white; padding: 10px 0; } </style> </head> <body> <header> <h1>这是一个简单的WebServer</h1> </header> <main> <p>这是一个简单的WebServer,你可以在这里放置一些内容。</p> <br/> <img src="23.png" alt="C++测试"> </main> <footer> <p> ©2025 My WebServer By HuJiaHang </p> </footer> </body> </html>
三、编译和运行
- 编译
g++ -std=c++20 WebServer.cpp -o WebServer //使用C++20标准,是因为std::string::ends_with()是C++20引入的功能
- 运行:执行编译好的WebServer程序
./WebServer
四、访问测试
使用浏览器访问http://localhost:8080,可以获取静态HTML页面、CSS样式、JavaScript脚本和图片
注意:如果使用的是云服务器,就必须要在安全组中放开端口
以下是我的测试
到此这篇关于C++实现HTTP服务的示例代码的文章就介绍到这了,更多相关C++ HTTP服务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
来源链接:https://www.jb51.net/program/3389353rr.htm
© 版权声明
本站所有资源来自于网络,仅供学习与参考,请勿用于商业用途,否则产生的一切后果将由您(转载者)自己承担!
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
THE END
暂无评论内容