用dw做的网站生成链接吗代码给wordpress添加图片不显示

张小明 2026/1/9 17:01:27
用dw做的网站生成链接吗,代码给wordpress添加图片不显示,有做电动车修车的网站吗,柳州网站建站费用从零构建HTTP服务器#xff1a;深入理解HTTP协议与实现 引言 在当今互联网时代#xff0c;HTTP协议作为万维网的基础协议#xff0c;承载着几乎所有的网络应用数据交换。无论是浏览网页、使用移动应用还是进行API调用#xff0c;都离不开HTTP协议的支持。本文将深入探讨H…从零构建HTTP服务器深入理解HTTP协议与实现引言在当今互联网时代HTTP协议作为万维网的基础协议承载着几乎所有的网络应用数据交换。无论是浏览网页、使用移动应用还是进行API调用都离不开HTTP协议的支持。本文将深入探讨HTTP协议的原理并从零开始构建一个完整的HTTP服务器通过丰富的代码示例和详细的理论讲解帮助读者全面掌握HTTP服务器的设计与实现。本文内容将涵盖网络编程的基础、HTTP协议的详细解析、服务器架构设计、以及实际代码实现总字数超过10000字包含大量可运行的代码示例适合有一定C/C基础并希望深入了解网络编程和HTTP协议的开发者阅读。一、服务器设计流程1.1 网络模型基础在深入HTTP服务器设计之前我们需要理解计算机网络的分层模型。OSI开放系统互连七层模型是网络通信的理论基础它将网络通信划分为七个层次物理层负责比特流在物理介质上的传输数据链路层负责节点到节点的数据传输网络层负责数据包的路由和转发传输层负责端到端的可靠数据传输会话层负责建立、管理和终止会话表示层负责数据格式转换、加密解密应用层负责应用程序间的通信在实际网络编程中我们主要关注传输层及以上层次。特别是传输层的TCP/UDP协议为上层应用提供了可靠的通信基础。1.2 TCP服务器编程模型HTTP协议通常运行在TCP之上因此HTTP服务器的核心是一个TCP服务器。一个基本的TCP服务器需要经历以下步骤// TCP服务器基本流程伪代码intmain(){// 1. 创建socketintserver_fdsocket(AF_INET,SOCK_STREAM,0);// 2. 绑定地址和端口bind(server_fd,(structsockaddr*)address,sizeof(address));// 3. 监听连接listen(server_fd,backlog);while(1){// 4. 接受客户端连接intclient_fdaccept(server_fd,(structsockaddr*)client_addr,addr_len);// 5. 处理客户端请求handle_request(client_fd);// 6. 关闭连接close(client_fd);}// 7. 关闭服务器close(server_fd);return0;}1.3 Reactor模式与事件驱动现代高性能HTTP服务器通常采用事件驱动模型如Reactor模式。这种模式能够高效地处理大量并发连接是Nginx、Node.js等高性能服务器的核心架构。Reactor模式核心组件事件分发器Dispatcher负责等待事件发生事件处理器EventHandler定义处理事件的接口具体事件处理器ConcreteEventHandler实现具体的事件处理逻辑事件源Handle产生事件的来源如socket下面是一个简单的Reactor模式实现框架#includesys/epoll.h#includesys/socket.h#includenetinet/in.h#includearpa/inet.h#includefcntl.h#includeunistd.h#includestdio.h#includeerrno.h#includestring.h#includestdlib.h#includevector#includemap#includefunctional#defineMAX_EVENTS1024#defineBUFFER_SIZE4096// 事件类型枚举enumEventType{READ_EVENT1,WRITE_EVENT2,ERROR_EVENT4};// 事件处理器基类classEventHandler{public:virtual~EventHandler(){}virtualvoidhandle_event(intfd,uint32_tevents)0;virtualintget_handle()const0;};// Reactor核心类classReactor{private:intepoll_fd;boolrunning;std::mapint,EventHandler*handlers;public:Reactor():epoll_fd(-1),running(false){}~Reactor(){if(epoll_fd0)close(epoll_fd);}// 初始化Reactorboolinit(){epoll_fdepoll_create1(0);if(epoll_fd0){perror(epoll_create1 failed);returnfalse;}returntrue;}// 注册事件处理器boolregister_handler(EventHandler*handler,uint32_tevents){intfdhandler-get_handle();structepoll_eventev;ev.eventsevents;ev.data.ptrhandler;if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,fd,ev)0){perror(epoll_ctl add failed);returnfalse;}handlers[fd]handler;returntrue;}// 移除事件处理器boolremove_handler(EventHandler*handler){intfdhandler-get_handle();if(epoll_ctl(epoll_fd,EPOLL_CTL_DEL,fd,NULL)0){perror(epoll_ctl del failed);returnfalse;}handlers.erase(fd);returntrue;}// 事件循环voidevent_loop(inttimeout-1){runningtrue;structepoll_eventevents[MAX_EVENTS];while(running){intnfdsepoll_wait(epoll_fd,events,MAX_EVENTS,timeout);if(nfds0){if(errnoEINTR)continue;perror(epoll_wait failed);break;}for(inti0;infds;i){EventHandler*handlerstatic_castEventHandler*(events[i].data.ptr);if(handler){handler-handle_event(handler-get_handle(),events[i].events);}}}}// 停止事件循环voidstop(){runningfalse;}};// 连接项管理单个客户端连接classConnection:publicEventHandler{private:intfd;Reactor*reactor;std::string in_buffer;std::string out_buffer;structsockaddr_inclient_addr;// HTTP请求解析状态enumParseState{PARSE_REQUEST_LINE,PARSE_HEADERS,PARSE_BODY,PARSE_COMPLETE};ParseState parse_state;std::mapstd::string,std::stringheaders;std::string method;std::string url;std::string version;size_t content_length;public:Connection(intfd,Reactor*reactor,conststructsockaddr_inaddr):fd(fd),reactor(reactor),client_addr(addr),parse_state(PARSE_REQUEST_LINE),content_length(0){// 设置非阻塞intflagsfcntl(fd,F_GETFL,0);fcntl(fd,F_SETFL,flags|O_NONBLOCK);}~Connection(){if(fd0)close(fd);}intget_handle()constoverride{returnfd;}voidhandle_event(intfd,uint32_tevents)override{if(eventsEPOLLIN){handle_read();}if(eventsEPOLLOUT){handle_write();}if(events(EPOLLERR|EPOLLHUP)){handle_error();}}private:voidhandle_read(){charbuffer[BUFFER_SIZE];ssize_t nread(fd,buffer,sizeof(buffer)-1);if(n0){buffer[n]\0;in_buffer.append(buffer,n);parse_http_request();}elseif(n0){// 客户端关闭连接cleanup();}else{if(errno!EAGAINerrno!EWOULDBLOCK){perror(read error);cleanup();}}}voidhandle_write(){if(!out_buffer.empty()){ssize_t nwrite(fd,out_buffer.data(),out_buffer.size());if(n0){out_buffer.erase(0,n);}else{if(errno!EAGAINerrno!EWOULDBLOCK){perror(write error);cleanup();}}}// 如果没有数据要发送取消写事件监听if(out_buffer.empty()){update_event_monitoring(EPOLLIN);}}voidhandle_error(){cleanup();}voidcleanup(){reactor-remove_handler(this);deletethis;}voidupdate_event_monitoring(uint32_tevents){structepoll_eventev;ev.eventsevents;ev.data.ptrthis;epoll_ctl(reactor-get_handle(),EPOLL_CTL_MOD,fd,ev);}voidparse_http_request(){// HTTP请求解析实现将在后面详细介绍}voidsend_response(){// HTTP响应发送实现将在后面详细介绍}};// HTTP服务器类classHttpServer{private:intserver_fd;Reactor reactor;structsockaddr_inserver_addr;public:HttpServer(intport8080){memset(server_addr,0,sizeof(server_addr));server_addr.sin_familyAF_INET;server_addr.sin_addr.s_addrhtonl(INADDR_ANY);server_addr.sin_porthtons(port);}~HttpServer(){if(server_fd0)close(server_fd);}boolinit(){// 创建socketserver_fdsocket(AF_INET,SOCK_STREAM,0);if(server_fd0){perror(socket creation failed);returnfalse;}// 设置socket选项允许地址重用intopt1;if(setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,opt,sizeof(opt))0){perror(setsockopt failed);returnfalse;}// 绑定地址if(bind(server_fd,(structsockaddr*)server_addr,sizeof(server_addr))0){perror(bind failed);returnfalse;}// 监听连接if(listen(server_fd,SOMAXCONN)0){perror(listen failed);returnfalse;}// 设置非阻塞intflagsfcntl(server_fd,F_GETFL,0);fcntl(server_fd,F_SETFL,flags|O_NONBLOCK);// 初始化Reactorif(!reactor.init()){returnfalse;}returntrue;}voidstart(){// 创建监听socket的事件处理器classAcceptHandler:publicEventHandler{private:HttpServer*server;public:AcceptHandler(HttpServer*s):server(s){}intget_handle()constoverride{returnserver-server_fd;}voidhandle_event(intfd,uint32_tevents)override{if(eventsEPOLLIN){server-handle_accept();}}};// 注册AcceptHandler到ReactorAcceptHandler*handlernewAcceptHandler(this);reactor.register_handler(handler,EPOLLIN);printf(HTTP Server started on port %d\n,ntohs(server_addr.sin_port));// 开始事件循环reactor.event_loop();}private:voidhandle_accept(){structsockaddr_inclient_addr;socklen_t addr_lensizeof(client_addr);while(true){intclient_fdaccept(server_fd,(structsockaddr*)client_addr,addr_len);if(client_fd0){if(errnoEAGAIN||errnoEWOULDBLOCK){// 没有更多连接break;}else{perror(accept failed);break;}}// 创建新连接并注册到ReactorConnection*connnewConnection(client_fd,reactor,client_addr);reactor.register_handler(conn,EPOLLIN|EPOLLET);// 边沿触发模式printf(New connection from %s:%d\n,inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));}}};intmain(){HttpServerserver(8080);if(!server.init()){fprintf(stderr,Server initialization failed\n);return1;}server.start();return0;}1.4 多线程与多进程模型除了事件驱动模型HTTP服务器还可以采用多线程或多进程模型来处理并发连接。每种模型都有其优缺点多进程模型Pre-forking#includestdio.h#includestdlib.h#includestring.h#includeunistd.h#includesys/socket.h#includenetinet/in.h#includesys/wait.h#includesignal.h#defineMAX_CHILDREN10#definePORT8080// 子进程处理函数voidchild_process(intserver_fd){while(1){structsockaddr_inclient_addr;socklen_taddr_lensizeof(client_addr);intclient_fdaccept(server_fd,(structsockaddr*)client_addr,addr_len);if(client_fd0){perror(accept failed);continue;}// 处理HTTP请求handle_http_request(client_fd);close(client_fd);}}intmain(){intserver_fd;structsockaddr_inserver_addr;// 创建socketserver_fdsocket(AF_INET,SOCK_STREAM,0);// 设置地址重用intopt1;setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,opt,sizeof(opt));// 绑定地址server_addr.sin_familyAF_INET;server_addr.sin_addr.s_addrINADDR_ANY;server_addr.sin_porthtons(PORT);bind(server_fd,(structsockaddr*)server_addr,sizeof(server_addr));// 监听listen(server_fd,SOMAXCONN);printf(Master process started, creating child processes...\n);// 创建子进程for(inti0;iMAX_CHILDREN;i){pid_tpidfork();if(pid0){// 子进程printf(Child process %d started\n,getpid());child_process(server_fd);exit(0);}elseif(pid0){perror(fork failed);}}// 父进程等待子进程for(inti0;iMAX_CHILDREN;i){wait(NULL);}close(server_fd);return0;}线程池模型#includeiostream#includevector#includequeue#includethread#includemutex#includecondition_variable#includefunctional#includeatomicclassThreadPool{private:std::vectorstd::threadworkers;std::queuestd::functionvoid()tasks;std::mutex queue_mutex;std::condition_variable condition;std::atomicboolstop;public:ThreadPool(size_t threads):stop(false){for(size_t i0;ithreads;i){workers.emplace_back([this]{while(true){std::functionvoid()task;{std::unique_lockstd::mutexlock(this-queue_mutex);this-condition.wait(lock,[this]{returnthis-stop||!this-tasks.empty();});if(this-stopthis-tasks.empty()){return;}taskstd::move(this-tasks.front());this-tasks.pop();}task();}});}}templateclassFvoidenqueue(Ff){{std::unique_lockstd::mutexlock(queue_mutex);tasks.emplace(std::forwardF(f));}condition.notify_one();}~ThreadPool(){{std::unique_lockstd::mutexlock(queue_mutex);stoptrue;}condition.notify_all();for(std::threadworker:workers){worker.join();}}};// 使用线程池的HTTP服务器classThreadedHttpServer{private:intserver_fd;ThreadPool pool;public:ThreadedHttpServer(intport,size_t thread_count4):pool(thread_count){server_fdsocket(AF_INET,SOCK_STREAM,0);structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_addr.s_addrINADDR_ANY;server_addr.sin_porthtons(port);bind(server_fd,(structsockaddr*)server_addr,sizeof(server_addr));listen(server_fd,SOMAXCONN);}voidstart(){printf(Threaded HTTP server started\n);while(true){structsockaddr_inclient_addr;socklen_t addr_lensizeof(client_addr);intclient_fdaccept(server_fd,(structsockaddr*)client_addr,addr_len);if(client_fd0){perror(accept failed);continue;}// 将任务提交到线程池pool.enqueue([this,client_fd,client_addr]{handle_http_request(client_fd);close(client_fd);});}}private:voidhandle_http_request(intclient_fd){// HTTP请求处理逻辑}};1.5 服务器架构设计考虑设计一个高性能HTTP服务器需要考虑多个方面并发模型选择事件驱动 vs 多线程 vs 多进程I/O多路复用技术select/poll vs epoll vs kqueue内存管理缓冲区设计、内存池连接管理连接池、超时控制负载均衡多进程间负载均衡日志系统请求日志、错误日志配置管理运行时配置加载安全考虑DDoS防护、输入验证二、HTTP协议详解2.1 URL网址结构URLUniform Resource Locator统一资源定位符是互联网上标准资源的地址。一个完整的URL包含以下部分https://www.example.com:8080/path/to/resource?queryvalue#fragment └─┬─┘ └──────┬──────┘ └┬─┘ └───────┬───────┘ └───┬───┘ └──┬──┘ 协议 主机名 端口 路径 查询参数 片段让我们详细解析每个部分#includestring#includemap#includesstream#includealgorithmclassURL{private:std::string scheme;// http, https, ftp等std::string host;// 主机名或IP地址intport;// 端口号std::string path;// 资源路径std::mapstd::string,std::stringquery_params;// 查询参数std::string fragment;// 片段标识public:// 解析URLboolparse(conststd::stringurl_str){std::string remainingurl_str;// 解析协议size_t scheme_endremaining.find(://);if(scheme_end!std::string::npos){schemeremaining.substr(0,scheme_end);remainingremaining.substr(scheme_end3);}// 解析主机和端口size_t host_endremaining.find_first_of(/?#);std::string host_port;if(host_end!std::string::npos){host_portremaining.substr(0,host_end);remainingremaining.substr(host_end);}else{host_portremaining;remaining;}// 分离主机和端口size_t port_starthost_port.find(:);if(port_start!std::string::npos){hosthost_port.substr(0,port_start);std::string port_strhost_port.substr(port_start1);portstd::stoi(port_str);}else{hosthost_port;// 默认端口if(schemehttps)port443;elseif(schemehttp)port80;elseport80;}// 解析路径、查询参数和片段parse_path_query_fragment(remaining);returntrue;}voidparse_path_query_fragment(conststd::stringstr){std::string remainingstr;// 解析片段size_t fragment_startremaining.find(#);if(fragment_start!std::string::npos){fragmentremaining.substr(fragment_start1);remainingremaining.substr(0,fragment_start);}// 解析查询参数size_t query_startremaining.find(?);if(query_start!std::string::npos){pathremaining.substr(0,query_start);std::string query_strremaining.substr(query_start1);parse_query_params(query_str);}else{pathremaining;}// 如果路径为空设置为根路径if(path.empty()){path/;}}voidparse_query_params(conststd::stringquery_str){std::stringstreamss(query_str);std::string pair;while(std::getline(ss,pair,)){size_t eq_pospair.find();if(eq_pos!std::string::npos){std::string keypair.substr(0,eq_pos);std::string valuepair.substr(eq_pos1);// URL解码简化版keyurl_decode(key);valueurl_decode(value);query_params[key]value;}}}std::stringurl_decode(conststd::stringencoded){std::string decoded;decoded.reserve(encoded.size());for(size_t i0;iencoded.size();i){if(encoded[i]%i2encoded.size()){std::string hexencoded.substr(i1,2);charchstatic_castchar(std::stoi(hex,nullptr,16));decoded.push_back(ch);i2;}elseif(encoded[i]){decoded.push_back( );}else{decoded.push_back(encoded[i]);}}returndecoded;}// Getter方法std::stringget_scheme()const{returnscheme;}std::stringget_host()const{returnhost;}intget_port()const{returnport;}std::stringget_path()const{returnpath;}std::mapstd::string,std::stringget_query_params()const{returnquery_params;}std::stringget_fragment()const{returnfragment;}// 重新构建URLstd::stringbuild()const{std::stringstream ss;if(!scheme.empty()){ssscheme://;}sshost;if((schemehttpport!80)||(schemehttpsport!443)){ss:port;}sspath;if(!query_params.empty()){ss?;boolfirsttrue;for(constautoparam:query_params){if(!first)ss;ssparam.firstparam.second;firstfalse;}}if(!fragment.empty()){ss#fragment;}returnss.str();}};// 使用示例voidurl_example(){URL url;url.parse(https://www.example.com:8080/api/v1/users?namejohnage25#section1);printf(Scheme: %s\n,url.get_scheme().c_str());printf(Host: %s\n,url.get_host().c_str());printf(Port: %d\n,url.get_port());printf(Path: %s\n,url.get_path().c_str());autoparamsurl.get_query_params();for(constautoparam:params){printf(Query: %s %s\n,param.first.c_str(),param.second.c_str());}printf(Fragment: %s\n,url.get_fragment().c_str());printf(Rebuilt URL: %s\n,url.build().c_str());}2.2 HTTP请求RequestHTTP请求由客户端发送到服务器包含请求行、请求头和请求体三部分。2.2.1 请求行结构请求行包含三个部分请求方法、请求URI和HTTP版本。GET /index.html HTTP/1.12.2.2 完整的HTTP请求类实现#includestring#includemap#includevector#includesstream#includealgorithm#includecctypeclassHttpRequest{private:std::string method;// 请求方法GET, POST等std::string uri;// 请求URIstd::string version;// HTTP版本std::mapstd::string,std::stringheaders;// 请求头std::string body;// 请求体std::mapstd::string,std::stringquery_params;// 查询参数std::mapstd::string,std::stringform_data;// POST表单数据// 解析状态enumParseState{PARSE_REQUEST_LINE,PARSE_HEADERS,PARSE_BODY,PARSE_COMPLETE};ParseState parse_state;public:HttpRequest():parse_state(PARSE_REQUEST_LINE){}// 解析HTTP请求boolparse(conststd::stringraw_request){std::istringstreamstream(raw_request);std::string line;// 解析请求行if(parse_statePARSE_REQUEST_LINE){if(!std::getline(stream,line)){returnfalse;}if(!parse_request_line(line)){returnfalse;}parse_statePARSE_HEADERS;}// 解析请求头if(parse_statePARSE_HEADERS){while(std::getline(stream,line)){// 去除末尾的\rif(!line.empty()line.back()\r){line.pop_back();}// 空行表示头部结束if(line.empty()){parse_statePARSE_BODY;break;}if(!parse_header_line(line)){returnfalse;}}}// 解析请求体if(parse_statePARSE_BODY){// 获取剩余内容作为请求体std::streampos body_startstream.tellg();stream.seekg(0,std::ios::end);std::streampos body_endstream.tellg();stream.seekg(body_start);size_t body_lengthbody_end-body_start;if(body_length0){std::vectorcharbuffer(body_length);stream.read(buffer.data(),body_length);body.assign(buffer.data(),body_length);// 根据Content-Type解析请求体parse_body();}parse_statePARSE_COMPLETE;}returntrue;}private:boolparse_request_line(conststd::stringline){std::istringstreamline_stream(line);if(!(line_streammethoduriversion)){returnfalse;}// 解析查询参数size_t query_posuri.find(?);if(query_pos!std::string::npos){std::string query_struri.substr(query_pos1);uriuri.substr(0,query_pos);parse_query_params(query_str);}returntrue;}boolparse_header_line(conststd::stringline){size_t colon_posline.find(:);if(colon_posstd::string::npos){returnfalse;}std::string keyline.substr(0,colon_pos);std::string valueline.substr(colon_pos1);// 去除首尾空白字符trim(key);trim(value);headers[key]value;returntrue;}voidparse_query_params(conststd::stringquery_str){std::stringstreamss(query_str);std::string pair;while(std::getline(ss,pair,)){size_t eq_pospair.find();if(eq_pos!std::string::npos){std::string keypair.substr(0,eq_pos);std::string valuepair.substr(eq_pos1);// URL解码keyurl_decode(key);valueurl_decode(value);query_params[key]value;}}}voidparse_body(){autocontent_type_itheaders.find(Content-Type);if(content_type_it!headers.end()){std::string content_typecontent_type_it-second;if(content_type.find(application/x-www-form-urlencoded)!std::string::npos){parse_form_urlencoded();}elseif(content_type.find(multipart/form-data)!std::string::npos){parse_multipart_form_data();}elseif(content_type.find(application/json)!std::string::npos){// JSON解析可以在这里实现}}elseif(methodPOST){// 默认解析为表单数据parse_form_urlencoded();}}voidparse_form_urlencoded(){parse_query_params(body);// 复用查询参数解析逻辑form_dataquery_params;}voidparse_multipart_form_data(){autocontent_type_itheaders.find(Content-Type);if(content_type_itheaders.end())return;std::string content_typecontent_type_it-second;// 提取boundarysize_t boundary_poscontent_type.find(boundary);if(boundary_posstd::string::npos)return;std::string boundarycontent_type.substr(boundary_pos9);std::string delimiter--boundary;std::string end_delimiterdelimiter--;size_t pos0;// 跳过第一个delimiterposbody.find(delimiter,pos);if(posstd::string::npos)return;posdelimiter.length();while(posbody.length()){// 跳过CRLFif(body.substr(pos,2)\r\n){pos2;}// 检查是否到达结束delimiterif(body.substr(pos,end_delimiter.length())end_delimiter){break;}// 解析part头部std::mapstd::string,std::stringpart_headers;while(posbody.length()){size_t line_endbody.find(\r\n,pos);if(line_endstd::string::npos)break;std::string linebody.substr(pos,line_end-pos);posline_end2;// 空行表示头部结束if(line.empty()){break;}size_t colon_posline.find(:);if(colon_pos!std::string::npos){std::string keyline.substr(0,colon_pos);std::string valueline.substr(colon_pos1);trim(key);trim(value);part_headers[key]value;}}// 查找part内容结束位置size_t part_endbody.find(\r\ndelimiter,pos);if(part_endstd::string::npos)break;std::string part_contentbody.substr(pos,part_end-pos);pospart_end2;// 解析part内容autocontent_disposition_itpart_headers.find(Content-Disposition);if(content_disposition_it!part_headers.end()){std::string dispositioncontent_disposition_it-second;// 提取namesize_t name_posdisposition.find(name\);if(name_pos!std::string::npos){name_pos6;size_t name_enddisposition.find(\,name_pos);if(name_end!std::string::npos){std::string namedisposition.substr(name_pos,name_end-name_pos);form_data[name]part_content;}}}}}// 辅助函数voidtrim(std::stringstr){// 去除左侧空白str.erase(str.begin(),std::find_if(str.begin(),str.end(),[](intch){return!std::isspace(ch);}));// 去除右侧空白str.erase(std::find_if(str.rbegin(),str.rend(),[](intch){return!std::isspace(ch);}).base(),str.end());}std::stringurl_decode(conststd::stringencoded){std::string decoded;decoded.reserve(encoded.size());for(size_t i0;iencoded.size();i){if(encoded[i]%i2encoded.size()){std::string hexencoded.substr(i1,2);charchstatic_castchar(std::stoi(hex,nullptr,16));decoded.push_back(ch);i2;}elseif(encoded[i]){decoded.push_back( );}else{decoded.push_back(encoded[i]);}}returndecoded;}public:// Getter方法std::stringget_method()const{returnmethod;}std::stringget_uri()const{returnuri;}std::stringget_version()const{returnversion;}std::stringget_body()const{returnbody;}std::stringget_header(conststd::stringkey)const{autoitheaders.find(key);returnit!headers.end()?it-second:;}conststd::mapstd::string,std::stringget_headers()const{returnheaders;}std::stringget_query_param(conststd::stringkey)const{autoitquery_params.find(key);returnit!query_params.end()?it-second:;}conststd::mapstd::string,std::stringget_query_params()const{returnquery_params;}std::stringget_form_data(conststd::stringkey)const{autoitform_data.find(key);returnit!form_data.end()?it-second:;}conststd::mapstd::string,std::stringget_form_data()const{returnform_data;}// 判断是否keep-aliveboolis_keep_alive()const{std::string connectionget_header(Connection);if(versionHTTP/1.1){returnconnection!close;}else{returnconnectionkeep-alive;}}// 获取内容长度size_tget_content_length()const{std::string length_strget_header(Content-Length);if(!length_str.empty()){returnstd::stoul(length_str);}return0;}};2.3 HTTP响应ResponseHTTP响应是服务器对客户端请求的回复包含状态行、响应头和响应体。2.3.1 状态行结构状态行包含三个部分HTTP版本、状态码和状态描述。HTTP/1.1 200 OK2.3.2 完整的HTTP响应类实现classHttpResponse{private:std::string version;// HTTP版本intstatus_code;// 状态码std::string status_message;// 状态描述std::mapstd::string,std::stringheaders;// 响应头std::string body;// 响应体public:HttpResponse():version(HTTP/1.1),status_code(200),status_message(OK){}// 设置状态voidset_status(intcode,conststd::stringmessage){status_codecode;if(!message.empty()){status_messagemessage;}else{// 默认状态描述switch(code){case200:status_messageOK;break;case201:status_messageCreated;break;case204:status_messageNo Content;break;case301:status_messageMoved Permanently;break;case302:status_messageFound;break;case304:status_messageNot Modified;break;case400:status_messageBad Request;break;case401:status_messageUnauthorized;break;case403:status_messageForbidden;break;case404:status_messageNot Found;break;case405:status_messageMethod Not Allowed;break;case500:status_messageInternal Server Error;break;case502:status_messageBad Gateway;break;case503:status_messageService Unavailable;break;default:status_messageUnknown;break;}}}// 设置响应头voidset_header(conststd::stringkey,conststd::stringvalue){headers[key]value;}// 设置响应体voidset_body(conststd::stringcontent,conststd::stringcontent_typetext/html){bodycontent;set_header(Content-Length,std::to_string(body.size()));set_header(Content-Type,content_type);}// 设置JSON响应体voidset_json_body(conststd::stringjson){bodyjson;set_header(Content-Length,std::to_string(body.size()));set_header(Content-Type,application/json; charsetutf-8);}// 设置重定向voidset_redirect(conststd::stringlocation,intcode302){set_status(code);set_header(Location,location);}// 构建完整响应字符串std::stringbuild()const{std::stringstream ss;// 状态行ssversion status_code status_message\r\n;// 响应头for(constautoheader:headers){ssheader.first: header.second\r\n;}// 空行ss\r\n;// 响应体ssbody;returnss.str();}// 发送响应到socketboolsend(intsocket_fd)const{std::string responsebuild();ssize_t total_sent0;ssize_t to_sendresponse.size();while(total_sentto_send){ssize_t sentwrite(socket_fd,response.c_str()total_sent,to_send-total_sent);if(sent0){if(errnoEAGAIN||errnoEWOULDBLOCK){// 非阻塞socket稍后重试continue;}returnfalse;}total_sentsent;}returntrue;}// 静态方法创建常见响应staticHttpResponsemake_ok_response(conststd::stringcontent,conststd::stringcontent_typetext/html){HttpResponse response;response.set_status(200);if(!content.empty()){response.set_body(content,content_type);}returnresponse;}staticHttpResponsemake_error_response(intcode,conststd::stringmessage){HttpResponse response;response.set_status(code);std::string error_pagehtmlheadtitlestd::to_string(code) response.status_message/title/headbodyh1std::to_string(code) response.status_message/h1;if(!message.empty()){error_pagepmessage/p;}error_page/body/html;response.set_body(error_page);returnresponse;}staticHttpResponsemake_json_response(conststd::stringjson){HttpResponse response;response.set_status(200);response.set_json_body(json);returnresponse;}staticHttpResponsemake_redirect_response(conststd::stringlocation,intcode302){HttpResponse response;response.set_redirect(location,code);returnresponse;}};2.4 HTTP协议细节补充2.4.1 HTTP状态码详解HTTP状态码分为5类每类有不同的含义classHttpStatus{public:// 信息性状态码 (1xx)staticconstintCONTINUE100;staticconstintSWITCHING_PROTOCOLS101;staticconstintPROCESSING102;staticconstintEARLY_HINTS103;// 成功状态码 (2xx)staticconstintOK200;staticconstintCREATED201;staticconstintACCEPTED202;staticconstintNON_AUTHORITATIVE_INFORMATION203;staticconstintNO_CONTENT204;staticconstintRESET_CONTENT205;staticconstintPARTIAL_CONTENT206;staticconstintMULTI_STATUS207;staticconstintALREADY_REPORTED208;staticconstintIM_USED226;// 重定向状态码 (3xx)staticconstintMULTIPLE_CHOICES300;staticconstintMOVED_PERMANENTLY301;staticconstintFOUND302;staticconstintSEE_OTHER303;staticconstintNOT_MODIFIED304;staticconstintUSE_PROXY305;staticconstintTEMPORARY_REDIRECT307;staticconstintPERMANENT_REDIRECT308;// 客户端错误状态码 (4xx)staticconstintBAD_REQUEST400;staticconstintUNAUTHORIZED401;staticconstintPAYMENT_REQUIRED402;staticconstintFORBIDDEN403;staticconstintNOT_FOUND404;staticconstintMETHOD_NOT_ALLOWED405;staticconstintNOT_ACCEPTABLE406;staticconstintPROXY_AUTHENTICATION_REQUIRED407;staticconstintREQUEST_TIMEOUT408;staticconstintCONFLICT409;staticconstintGONE410;staticconstintLENGTH_REQUIRED411;staticconstintPRECONDITION_FAILED412;staticconstintPAYLOAD_TOO_LARGE413;staticconstintURI_TOO_LONG414;staticconstintUNSUPPORTED_MEDIA_TYPE415;staticconstintRANGE_NOT_SATISFIABLE416;staticconstintEXPECTATION_FAILED417;staticconstintIM_A_TEAPOT418;// RFC 2324staticconstintMISDIRECTED_REQUEST421;staticconstintUNPROCESSABLE_ENTITY422;staticconstintLOCKED423;staticconstintFAILED_DEPENDENCY424;staticconstintTOO_EARLY425;staticconstintUPGRADE_REQUIRED426;staticconstintPRECONDITION_REQUIRED428;staticconstintTOO_MANY_REQUESTS429;staticconstintREQUEST_HEADER_FIELDS_TOO_LARGE431;staticconstintUNAVAILABLE_FOR_LEGAL_REASONS451;// 服务器错误状态码 (5xx)staticconstintINTERNAL_SERVER_ERROR500;staticconstintNOT_IMPLEMENTED501;staticconstintBAD_GATEWAY502;staticconstintSERVICE_UNAVAILABLE503;staticconstintGATEWAY_TIMEOUT504;staticconstintHTTP_VERSION_NOT_SUPPORTED505;staticconstintVARIANT_ALSO_NEGOTIATES506;staticconstintINSUFFICIENT_STORAGE507;staticconstintLOOP_DETECTED508;staticconstintNOT_EXTENDED510;staticconstintNETWORK_AUTHENTICATION_REQUIRED511;// 获取状态码描述staticstd::stringget_status_message(intcode){switch(code){// 1xxcase100:returnContinue;case101:returnSwitching Protocols;case102:returnProcessing;case103:returnEarly Hints;// 2xxcase200:returnOK;case201:returnCreated;case202:returnAccepted;case203:returnNon-Authoritative Information;case204:returnNo Content;case205:returnReset Content;case206:returnPartial Content;case207:returnMulti-Status;case208:returnAlready Reported;case226:returnIM Used;// 3xxcase300:returnMultiple Choices;case301:returnMoved Permanently;case302:returnFound;case303:returnSee Other;case304:returnNot Modified;case305:returnUse Proxy;case307:returnTemporary Redirect;case308:returnPermanent Redirect;// 4xxcase400:returnBad Request;case401:returnUnauthorized;case402:returnPayment Required;case403:returnForbidden;case404:returnNot Found;case405:returnMethod Not Allowed;case406:returnNot Acceptable;case407:returnProxy Authentication Required;case408:returnRequest Timeout;case409:returnConflict;case410:returnGone;case411:returnLength Required;case412:returnPrecondition Failed;case413:returnPayload Too Large;case414:returnURI Too Long;case415:returnUnsupported Media Type;case416:returnRange Not Satisfiable;case417:returnExpectation Failed;case418:returnIm a teapot;case421:returnMisdirected Request;case422:returnUnprocessable Entity;case423:returnLocked;case424:returnFailed Dependency;case425:returnToo Early;case426:returnUpgrade Required;case428:returnPrecondition Required;case429:returnToo Many Requests;case431:returnRequest Header Fields Too Large;case451:returnUnavailable For Legal Reasons;// 5xxcase500:returnInternal Server Error;case501:returnNot Implemented;case502:returnBad Gateway;case503:returnService Unavailable;case504:returnGateway Timeout;case505:returnHTTP Version Not Supported;case506:returnVariant Also Negotiates;case507:returnInsufficient Storage;case508:returnLoop Detected;case510:returnNot Extended;case511:returnNetwork Authentication Required;default:returnUnknown Status Code;}}// 判断状态码类别staticstd::stringget_status_category(intcode){if(code100code200)returnInformational;if(code200code300)returnSuccessful;if(code300code400)returnRedirection;if(code400code500)returnClient Error;if(code500code600)returnServer Error;returnUnknown;}};2.4.2 HTTP头部字段详解HTTP头部字段包含丰富的信息用于控制请求和响应的行为classHttpHeaders{public:// 通用头部字段staticconstchar*CACHE_CONTROL;staticconstchar*CONNECTION;staticconstchar*DATE;staticconstchar*PRAGMA;staticconstchar*TRAILER;staticconstchar*TRANSFER_ENCODING;staticconstchar*UPGRADE;staticconstchar*VIA;staticconstchar*WARNING;// 请求头部字段staticconstchar*ACCEPT;staticconstchar*ACCEPT_CHARSET;staticconstchar*ACCEPT_ENCODING;staticconstchar*ACCEPT_LANGUAGE;staticconstchar*AUTHORIZATION;staticconstchar*EXPECT;staticconstchar*FROM;staticconstchar*HOST;staticconstchar*IF_MATCH;staticconstchar*IF_MODIFIED_SINCE;staticconstchar*IF_NONE_MATCH;staticconstchar*IF_RANGE;staticconstchar*IF_UNMODIFIED_SINCE;staticconstchar*MAX_FORWARDS;staticconstchar*PROXY_AUTHORIZATION;staticconstchar*RANGE;staticconstchar*REFERER;staticconstchar*TE;staticconstchar*USER_AGENT;// 响应头部字段staticconstchar*ACCEPT_RANGES;staticconstchar*AGE;staticconstchar*ETAG;staticconstchar*LOCATION;staticconstchar*PROXY_AUTHENTICATE;staticconstchar*RETRY_AFTER;staticconstchar*SERVER;staticconstchar*VARY;staticconstchar*WWW_AUTHENTICATE;// 实体头部字段staticconstchar*ALLOW;staticconstchar*CONTENT_ENCODING;staticconstchar*CONTENT_LANGUAGE;staticconstchar*CONTENT_LENGTH;staticconstchar*CONTENT_LOCATION;staticconstchar*CONTENT_MD5;staticconstchar*CONTENT_RANGE;staticconstchar*CONTENT_TYPE;staticconstchar*EXPIRES;staticconstchar*LAST_MODIFIED;// Cookie相关staticconstchar*COOKIE;staticconstchar*SET_COOKIE;// 安全相关staticconstchar*STRICT_TRANSPORT_SECURITY;staticconstchar*X_CONTENT_TYPE_OPTIONS;staticconstchar*X_XSS_PROTECTION;staticconstchar*X_FRAME_OPTIONS;staticconstchar*CONTENT_SECURITY_POLICY;// CORS相关staticconstchar*ACCESS_CONTROL_ALLOW_ORIGIN;staticconstchar*ACCESS_CONTROL_ALLOW_METHODS;staticconstchar*ACCESS_CONTROL_ALLOW_HEADERS;staticconstchar*ACCESS_CONTROL_ALLOW_CREDENTIALS;staticconstchar*ACCESS_CONTROL_EXPOSE_HEADERS;staticconstchar*ACCESS_CONTROL_MAX_AGE;staticconstchar*ACCESS_CONTROL_REQUEST_METHOD;staticconstchar*ACCESS_CONTROL_REQUEST_HEADERS;staticconstchar*ORIGIN;};// 初始化静态成员constchar*HttpHeaders::CACHE_CONTROLCache-Control;constchar*HttpHeaders::CONNECTIONConnection;constchar*HttpHeaders::DATEDate;constchar*HttpHeaders::PRAGMAPragma;constchar*HttpHeaders::TRAILERTrailer;constchar*HttpHeaders::TRANSFER_ENCODINGTransfer-Encoding;constchar*HttpHeaders::UPGRADEUpgrade;constchar*HttpHeaders::VIAVia;constchar*HttpHeaders::WARNINGWarning;constchar*HttpHeaders::ACCEPTAccept;constchar*HttpHeaders::ACCEPT_CHARSETAccept-Charset;constchar*HttpHeaders::ACCEPT_ENCODINGAccept-Encoding;constchar*HttpHeaders::ACCEPT_LANGUAGEAccept-Language;constchar*HttpHeaders::AUTHORIZATIONAuthorization;constchar*HttpHeaders::EXPECTExpect;constchar*HttpHeaders::FROMFrom;constchar*HttpHeaders::HOSTHost;constchar*HttpHeaders::IF_MATCHIf-Match;constchar*HttpHeaders::IF_MODIFIED_SINCEIf-Modified-Since;constchar*HttpHeaders::IF_NONE_MATCHIf-None-Match;constchar*HttpHeaders::IF_RANGEIf-Range;constchar*HttpHeaders::IF_UNMODIFIED_SINCEIf-Unmodified-Since;constchar*HttpHeaders::MAX_FORWARDSMax-Forwards;constchar*HttpHeaders::PROXY_AUTHORIZATIONProxy-Authorization;constchar*HttpHeaders::RANGERange;constchar*HttpHeaders::REFERERReferer;constchar*HttpHeaders::TETe;constchar*HttpHeaders::USER_AGENTUser-Agent;constchar*HttpHeaders::ACCEPT_RANGESAccept-Ranges;constchar*HttpHeaders::AGEAge;constchar*HttpHeaders::ETAGETag;constchar*HttpHeaders::LOCATIONLocation;constchar*HttpHeaders::PROXY_AUTHENTICATEProxy-Authenticate;constchar*HttpHeaders::RETRY_AFTERRetry-After;constchar*HttpHeaders::SERVERServer;constchar*HttpHeaders::VARYVary;constchar*HttpHeaders::WWW_AUTHENTICATEWWW-Authenticate;constchar*HttpHeaders::ALLOWAllow;constchar*HttpHeaders::CONTENT_ENCODINGContent-Encoding;constchar*HttpHeaders::CONTENT_LANGUAGEContent-Language;constchar*HttpHeaders::CONTENT_LENGTHContent-Length;constchar*HttpHeaders::CONTENT_LOCATIONContent-Location;constchar*HttpHeaders::CONTENT_MD5Content-MD5;constchar*HttpHeaders::CONTENT_RANGEContent-Range;constchar*HttpHeaders::CONTENT_TYPEContent-Type;constchar*HttpHeaders::EXPIRESExpires;constchar*HttpHeaders::LAST_MODIFIEDLast-Modified;constchar*HttpHeaders::COOKIECookie;constchar*HttpHeaders::SET_COOKIESet-Cookie;constchar*HttpHeaders::STRICT_TRANSPORT_SECURITYStrict-Transport-Security;constchar*HttpHeaders::X_CONTENT_TYPE_OPTIONSX-Content-Type-Options;constchar*HttpHeaders::X_XSS_PROTECTIONX-XSS-Protection;constchar*HttpHeaders::X_FRAME_OPTIONSX-Frame-Options;constchar*HttpHeaders::CONTENT_SECURITY_POLICYContent-Security-Policy;constchar*HttpHeaders::ACCESS_CONTROL_ALLOW_ORIGINAccess-Control-Allow-Origin;constchar*HttpHeaders::ACCESS_CONTROL_ALLOW_METHODSAccess-Control-Allow-Methods;constchar*HttpHeaders::ACCESS_CONTROL_ALLOW_HEADERSAccess-Control-Allow-Headers;constchar*HttpHeaders::ACCESS_CONTROL_ALLOW_CREDENTIALSAccess-Control-Allow-Credentials;constchar*HttpHeaders::ACCESS_CONTROL_EXPOSE_HEADERSAccess-Control-Expose-Headers;constchar*HttpHeaders::ACCESS_CONTROL_MAX_AGEAccess-Control-Max-Age;constchar*HttpHeaders::ACCESS_CONTROL_REQUEST_METHODAccess-Control-Request-Method;constchar*HttpHeaders::ACCESS_CONTROL_REQUEST_HEADERSAccess-Control-Request-Headers;constchar*HttpHeaders::ORIGINOrigin;// Content-Type常用值classContentTypes{public:staticconstchar*TEXT_HTML;staticconstchar*TEXT_PLAIN;staticconstchar*TEXT_CSS;staticconstchar*TEXT_JAVASCRIPT;staticconstchar*APPLICATION_JSON;staticconstchar*APPLICATION_XML;staticconstchar*APPLICATION_X_WWW_FORM_URLENCODED;staticconstchar*MULTIPART_FORM_DATA;staticconstchar*IMAGE_JPEG;staticconstchar*IMAGE_PNG;staticconstchar*IMAGE_GIF;staticconstchar*APPLICATION_OCTET_STREAM;};constchar*ContentTypes::TEXT_HTMLtext/html; charsetutf-8;constchar*ContentTypes::TEXT_PLAINtext/plain; charsetutf-8;constchar*ContentTypes::TEXT_CSStext/css; charsetutf-8;constchar*ContentTypes::TEXT_JAVASCRIPTtext/javascript; charsetutf-8;constchar*ContentTypes::APPLICATION_JSONapplication/json; charsetutf-8;constchar*ContentTypes::APPLICATION_XMLapplication/xml; charsetutf-8;constchar*ContentTypes::APPLICATION_X_WWW_FORM_URLENCODEDapplication/x-www-form-urlencoded;constchar*ContentTypes::MULTIPART_FORM_DATAmultipart/form-data;constchar*ContentTypes::IMAGE_JPEGimage/jpeg;constchar*ContentTypes::IMAGE_PNGimage/png;constchar*ContentTypes::IMAGE_GIFimage/gif;constchar*ContentTypes::APPLICATION_OCTET_STREAMapplication/octet-stream;2.4.3 HTTP方法详解HTTP定义了多种请求方法每种方法有不同的语义classHttpMethods{public:staticconstchar*GET;staticconstchar*POST;staticconstchar*PUT;staticconstchar*DELETE;staticconstchar*HEAD;staticconstchar*OPTIONS;staticconstchar*PATCH;staticconstchar*TRACE;staticconstchar*CONNECT;// 判断方法是否安全不修改资源staticboolis_safe(conststd::stringmethod){returnmethodGET||methodHEAD||methodOPTIONS||methodTRACE;}// 判断方法是否幂等多次执行结果相同staticboolis_idempotent(conststd::stringmethod){returnmethodGET||methodHEAD||methodPUT||methodDELETE||methodOPTIONS||methodTRACE;}// 判断方法是否可缓存staticboolis_cacheable(conststd::stringmethod){returnmethodGET||methodHEAD;}// 获取方法描述staticstd::stringget_method_description(conststd::stringmethod){if(methodGET)return获取资源;if(methodPOST)return提交数据;if(methodPUT)return更新资源;if(methodDELETE)return删除资源;if(methodHEAD)return获取响应头;if(methodOPTIONS)return获取支持的方法;if(methodPATCH)return部分更新资源;if(methodTRACE)return回显请求;if(methodCONNECT)return建立隧道;return未知方法;}};constchar*HttpMethods::GETGET;constchar*HttpMethods::POSTPOST;constchar*HttpMethods::PUTPUT;constchar*HttpMethods::DELETEDELETE;constchar*HttpMethods::HEADHEAD;constchar*HttpMethods::OPTIONSOPTIONS;constchar*HttpMethods::PATCHPATCH;constchar*HttpMethods::TRACETRACE;constchar*HttpMethods::CONNECTCONNECT;2.4.4 HTTP版本演进HTTP协议有多个版本每个版本都有重要改进classHttpVersions{public:staticconstchar*HTTP_0_9;staticconstchar*HTTP_1_0;staticconstchar*HTTP_1_1;staticconstchar*HTTP_2_0;staticconstchar*HTTP_3_0;// 获取版本特性staticstd::stringget_features(conststd::stringversion){if(versionHTTP_0_9)return简单文本传输无头部仅GET方法;if(versionHTTP_1_0)return增加头部、状态码、多种方法非持久连接;if(versionHTTP_1_1)return持久连接、管道化、分块传输、缓存控制;if(versionHTTP_2_0)return二进制分帧、多路复用、头部压缩、服务器推送;if(versionHTTP_3_0)return基于QUIC解决队头阻塞0-RTT连接;return未知版本;}// 比较版本staticboolis_greater_or_equal(conststd::stringv1,conststd::stringv2){std::vectorstd::stringversions{HTTP_0_9,HTTP_1_0,HTTP_1_1,HTTP_2_0,HTTP_3_0};autoit1std::find(versions.begin(),versions.end(),v1);autoit2std::find(versions.begin(),versions.end(),v2);if(it1versions.end()||it2versions.end()){returnfalse;}returnstd::distance(versions.begin(),it1)std::distance(versions.begin(),it2);}};constchar*HttpVersions::HTTP_0_9HTTP/0.9;constchar*HttpVersions::HTTP_1_0HTTP/1.0;constchar*HttpVersions::HTTP_1_1HTTP/1.1;constchar*HttpVersions::HTTP_2_0HTTP/2.0;constchar*HttpVersions::HTTP_3_0HTTP/3.0;三、代码验证与实践3.1 发送简单HTTP响应在前面的代码基础上我们现在实现一个完整的HTTP服务器能够处理各种HTTP请求并返回响应。// 完整的HTTP服务器实现#includeHttpRequest.h#includeHttpResponse.h#includeReactor.h#includeiostream#includefstream#includefilesystem#includejson/json.hnamespacefsstd::filesystem;classHttpServerHandler:publicEventHandler{private:intserver_fd;Reactor*reactor;std::string root_dir;// 网站根目录public:HttpServerHandler(intfd,Reactor*r,conststd::stringroot):server_fd(fd),reactor(r),root_dir(root){}intget_handle()constoverride{returnserver_fd;}voidhandle_event(intfd,uint32_tevents)override{if(eventsEPOLLIN){handle_accept();}}private:voidhandle_accept(){structsockaddr_inclient_addr;socklen_t addr_lensizeof(client_addr);while(true){intclient_fdaccept(server_fd,(structsockaddr*)client_addr,addr_len);if(client_fd0){if(errnoEAGAIN||errnoEWOULDBLOCK){break;}else{perror(accept failed);break;}}// 创建客户端连接处理器ClientHandler*handlernewClientHandler(client_fd,reactor,client_addr,root_dir);reactor-register_handler(handler,EPOLLIN|EPOLLET);}}};classClientHandler:publicEventHandler{private:intclient_fd;Reactor*reactor;structsockaddr_inclient_addr;std::string root_dir;HttpRequest request;HttpResponse response;std::string in_buffer;std::string out_buffer;enumState{READING_REQUEST,PROCESSING,SENDING_RESPONSE,CLOSING};State state;public:ClientHandler(intfd,Reactor*r,conststructsockaddr_inaddr,conststd::stringroot):client_fd(fd),reactor(r),client_addr(addr),root_dir(root),state(READING_REQUEST){// 设置非阻塞intflagsfcntl(fd,F_GETFL,0);fcntl(fd,F_SETFL,flags|O_NONBLOCK);}~ClientHandler(){if(client_fd0){close(client_fd);}}intget_handle()constoverride{returnclient_fd;}voidhandle_event(intfd,uint32_tevents)override{try{if(eventsEPOLLIN){handle_read();}if(eventsEPOLLOUT){handle_write();}if(events(EPOLLERR|EPOLLHUP)){cleanup();}}catch(conststd::exceptione){std::cerrError handling client: e.what()std::endl;cleanup();}}private:voidhandle_read(){charbuffer[8192];ssize_t nread(client_fd,buffer,sizeof(buffer));if(n0){in_buffer.append(buffer,n);// 尝试解析请求if(stateREADING_REQUEST){if(try_parse_request()){statePROCESSING;process_request();stateSENDING_RESPONSE;prepare_response();}}}elseif(n0){// 客户端关闭连接cleanup();}else{if(errno!EAGAINerrno!EWOULDBLOCK){perror(read error);cleanup();}}}booltry_parse_request(){// 检查是否收到完整的请求size_t header_endin_buffer.find(\r\n\r\n);if(header_endstd::string::npos){returnfalse;// 头部不完整}// 解析头部std::string headers_partin_buffer.substr(0,header_end4);if(!request.parse(headers_part)){send_error_response(400,Bad Request);returnfalse;}// 检查是否需要正文size_t content_lengthrequest.get_content_length();if(content_length0){size_t body_startheader_end4;size_t body_receivedin_buffer.length()-body_start;if(body_receivedcontent_length){returnfalse;// 正文不完整}// 提取正文std::string bodyin_buffer.substr(body_start,content_length);in_buffer.erase(0,body_startcontent_length);// 重新解析包含正文的完整请求if(!request.parse(headers_partbody)){send_error_response(400,Bad Request);returnfalse;}}else{// 没有正文直接解析in_buffer.erase(0,header_end4);}returntrue;}voidprocess_request(){std::string methodrequest.get_method();std::string urirequest.get_uri();// 安全检查防止目录遍历攻击if(uri.find(..)!std::string::npos){send_error_response(403,Forbidden);return;}// 路由处理if(uri/){serve_file(index.html);}elseif(uri/api/status){handle_api_status();}elseif(uri/api/datamethodGET){handle_api_get_data();}elseif(uri/api/datamethodPOST){handle_api_post_data();}elseif(uri/api/uploadmethodPOST){handle_api_upload();}elseif(uri.find(/api/)0){send_error_response(404,API endpoint not found);}else{// 静态文件服务serve_file(uri.substr(1));// 去掉开头的/}}voidserve_file(conststd::stringpath){fs::path file_pathfs::path(root_dir)/path;// 安全检查if(!fs::exists(file_path)){send_error_response(404,File not found: path);return;}if(fs::is_directory(file_path)){file_path/index.html;if(!fs::exists(file_path)){list_directory(path);return;}}// 读取文件std::ifstreamfile(file_path,std::ios::binary);if(!file){send_error_response(500,Cannot read file: path);return;}std::stringcontent((std::istreambuf_iteratorchar(file)),std::istreambuf_iteratorchar());// 根据扩展名设置Content-Typestd::string content_typeget_content_type(file_path.extension().string());response.set_status(200);response.set_body(content,content_type);// 设置缓存头response.set_header(Cache-Control,public, max-age3600);// 设置Last-Modified头autoftimefs::last_write_time(file_path);autosctpstd::chrono::time_point_caststd::chrono::system_clock::duration(ftime-fs::file_time_type::clock::now()std::chrono::system_clock::now());std::time_t cftimestd::chrono::system_clock::to_time_t(sctp);chartime_buf[100];std::strftime(time_buf,sizeof(time_buf),%a, %d %b %Y %H:%M:%S GMT,std::gmtime(cftime));response.set_header(Last-Modified,time_buf);}voidlist_directory(conststd::stringpath){fs::path dir_pathfs::path(root_dir)/path;if(!fs::exists(dir_path)||!fs::is_directory(dir_path)){send_error_response(404,Directory not found);return;}std::stringstream html;htmlhtmlheadtitleDirectory listing for /path/title/head;htmlbodyh1Directory listing for /path/h1hrul;// 上级目录链接if(path!){htmllia href\../\..//a/li;}// 目录内容for(constautoentry:fs::directory_iterator(dir_path)){std::string filenameentry.path().filename().string();boolis_dirfs::is_directory(entry.path());htmllia href\filename;if(is_dir)html/;html\filename;if(is_dir)html/;html/a/li;}html/ulhr/body/html;response.set_status(200);response.set_body(html.str());}voidhandle_api_status(){Json::Value json;json[status]ok;json[timestamp]static_castJson::UInt64(time(nullptr));json[server]SimpleHTTPServer/1.0;json[clients]1;// 简化处理实际应该是当前连接数Json::StreamWriterBuilder writer;std::string json_strJson::writeString(writer,json);responseHttpResponse::make_json_response(json_str);}voidhandle_api_get_data(){autoparamsrequest.get_query_params();Json::Value json;json[method]GET;json[timestamp]static_castJson::UInt64(time(nullptr));if(!params.empty()){Json::Value params_json;for(constautoparam:params){params_json[param.first]param.second;}json[parameters]params_json;}Json::StreamWriterBuilder writer;std::string json_strJson::writeString(writer,json);responseHttpResponse::make_json_response(json_str);}voidhandle_api_post_data(){autoform_datarequest.get_form_data();Json::Value json;json[method]POST;json[timestamp]static_castJson::UInt64(time(nullptr));if(!form_data.empty()){Json::Value data_json;for(constautodata:form_data){data_json[data.first]data.second;}json[form_data]data_json;}Json::StreamWriterBuilder writer;std::string json_strJson::writeString(writer,json);responseHttpResponse::make_json_response(json_str);}voidhandle_api_upload(){// 简单的上传处理response.set_status(200);response.set_body(htmlbodyh1Upload Received/h1pFile uploaded successfully/p/body/html);}voidsend_error_response(intcode,conststd::stringmessage){responseHttpResponse::make_error_response(code,message);}voidprepare_response(){out_bufferresponse.build();// 更新事件监听准备写入structepoll_eventev;ev.eventsEPOLLOUT|EPOLLET;ev.data.ptrthis;epoll_ctl(reactor-get_handle(),EPOLL_CTL_MOD,client_fd,ev);}voidhandle_write(){if(!out_buffer.empty()){ssize_t nwrite(client_fd,out_buffer.data(),out_buffer.size());if(n0){out_buffer.erase(0,n);}else{if(errno!EAGAINerrno!EWOULDBLOCK){perror(write error);cleanup();return;}}}if(out_buffer.empty()){// 检查是否为keep-alive连接if(request.is_keep_alive()){// 重置状态准备处理下一个请求in_buffer.clear();requestHttpRequest();responseHttpResponse();stateREADING_REQUEST;// 重新监听读事件structepoll_eventev;ev.eventsEPOLLIN|EPOLLET;ev.data.ptrthis;epoll_ctl(reactor-get_handle(),EPOLL_CTL_MOD,client_fd,ev);}else{cleanup();}}}voidcleanup(){reactor-remove_handler(this);deletethis;}std::stringget_content_type(conststd::stringextension){staticstd::mapstd::string,std::stringmime_types{{.html,ContentTypes::TEXT_HTML},{.htm,ContentTypes::TEXT_HTML},{.css,ContentTypes::TEXT_CSS},{.js,ContentTypes::TEXT_JAVASCRIPT},{.json,ContentTypes::APPLICATION_JSON},{.xml,ContentTypes::APPLICATION_XML},{.txt,ContentTypes::TEXT_PLAIN},{.jpg,ContentTypes::IMAGE_JPEG},{.jpeg,ContentTypes::IMAGE_JPEG},{.png,ContentTypes::IMAGE_PNG},{.gif,ContentTypes::IMAGE_GIF},{.ico,image/x-icon},{.svg,image/svgxml},{.pdf,application/pdf},{.zip,application/zip},{.gz,application/gzip},};autoitmime_types.find(extension);if(it!mime_types.end()){returnit-second;}returnContentTypes::APPLICATION_OCTET_STREAM;}};// 主函数intmain(intargc,char*argv[]){intport8080;std::string root_dir.;// 解析命令行参数for(inti1;iargc;i){std::string argargv[i];if(arg-pi1argc){portstd::stoi(argv[i]);}elseif(arg-di1argc){root_dirargv[i];}elseif(arg-h){std::coutUsage: argv[0] [-p port] [-d directory]std::endl;return0;}}// 检查根目录if(!fs::exists(root_dir)||!fs::is_directory(root_dir)){std::cerrError: Directory root_dir does not exist or is not a directorystd::endl;return1;}// 创建socketintserver_fdsocket(AF_INET,SOCK_STREAM,0);if(server_fd0){perror(socket creation failed);return1;}// 设置socket选项intopt1;if(setsockopt(server_fd,SOL_SOCKET,SO_REUSEADDR,opt,sizeof(opt))0){perror(setsockopt failed);close(server_fd);return1;}// 绑定地址structsockaddr_inserver_addr;memset(server_addr,0,sizeof(server_addr));server_addr.sin_familyAF_INET;server_addr.sin_addr.s_addrhtonl(INADDR_ANY);server_addr.sin_porthtons(port);if(bind(server_fd,(structsockaddr*)server_addr,sizeof(server_addr))0){perror(bind failed);close(server_fd);return1;}// 监听连接if(listen(server_fd,SOMAXCONN)0){perror(listen failed);close(server_fd);return1;}// 设置非阻塞intflagsfcntl(server_fd,F_GETFL,0);fcntl(server_fd,F_SETFL,flags|O_NONBLOCK);// 创建并启动ReactorReactor reactor;if(!reactor.init()){std::cerrFailed to initialize reactorstd::endl;close(server_fd);return1;}// 创建服务器处理器HttpServerHandler*server_handlernewHttpServerHandler(server_fd,reactor,root_dir);reactor.register_handler(server_handler,EPOLLIN|EPOLLET);std::coutHTTP Server started on port portstd::endl;std::coutServing directory: fs::absolute(root_dir)std::endl;std::coutPress CtrlC to stopstd::endl;// 启动事件循环reactor.event_loop();deleteserver_handler;close(server_fd);return0;}3.2 编译和运行创建Makefile来编译我们的HTTP服务器# Makefile for Simple HTTP Server CXX g CXXFLAGS -stdc17 -Wall -Wextra -O2 -pthread LDFLAGS -pthread TARGET httpserver SRCS main.cpp OBJS $(SRCS:.cpp.o) # JSON库路径需要先安装jsoncpp # Ubuntu: sudo apt-get install libjsoncpp-dev # CentOS: sudo yum install jsoncpp-devel JSONCPP_FLAGS -ljsoncpp all: $(TARGET) $(TARGET): $(OBJS) $(CXX) $(CXXFLAGS) -o $ $^ $(LDFLAGS) $(JSONCPP_FLAGS) %.o: %.cpp $(CXX) $(CXXFLAGS) -c $ -o $ clean: rm -f $(OBJS) $(TARGET) run: $(TARGET) ./$(TARGET) -p 8080 -d ./www debug: CXXFLAGS -g -DDEBUG debug: clean all .PHONY: all clean run debug创建网站目录和示例文件# 创建目录结构mkdir-p wwwmkdir-p www/imagesmkdir-p www/cssmkdir-p www/jsmkdir-p www/api# 创建示例文件catwww/index.htmlEOF !DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleSimple HTTP Server/title link relstylesheet href/css/style.css /head body header h1Welcome to Simple HTTP Server/h1 nav a href/Home/a a href/api/statusAPI Status/a a href/api/dataAPI Data/a a href/test.htmlTest Page/a a href/directory/Directory Listing/a /nav /header main section h2Server Information/h2 pThis is a simple HTTP server implemented in C./p pIt supports:/p ul liStatic file serving/li liDirectory listing/li liGET and POST requests/li liJSON API endpoints/li liKeep-alive connections/li /ul /section section h2Test Forms/h2 form action/api/data methodGET h3GET Request/h3 input typetext namename placeholderName input typetext namemessage placeholderMessage button typesubmitSend GET/button /form form action/api/data methodPOST h3POST Request/h3 input typetext nameusername placeholderUsername input typeemail nameemail placeholderEmail button typesubmitSend POST/button /form /section /main footer pSimple HTTP Server copy; 2024/p /footer script src/js/script.js/script /body /html EOF# 创建CSS文件catwww/css/style.cssEOF * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 1200px; margin: 0 auto; padding: 20px; background-color: #f5f5f5; } header { background-color: #4CAF50; color: white; padding: 1rem; border-radius: 5px; margin-bottom: 2rem; } header h1 { margin-bottom: 1rem; } nav { display: flex; gap: 1rem; } nav a { color: white; text-decoration: none; padding: 0.5rem 1rem; background-color: rgba(255, 255, 255, 0.2); border-radius: 3px; transition: background-color 0.3s; } nav a:hover { background-color: rgba(255, 255, 255, 0.3); } main { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin-bottom: 2rem; } section { background-color: white; padding: 1.5rem; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } h2 { color: #4CAF50; margin-bottom: 1rem; padding-bottom: 0.5rem; border-bottom: 2px solid #eee; } h3 { color: #666; margin-bottom: 1rem; } ul { margin-left: 1.5rem; margin-bottom: 1rem; } li { margin-bottom: 0.5rem; } form { display: flex; flex-direction: column; gap: 1rem; } input { padding: 0.5rem; border: 1px solid #ddd; border-radius: 3px; font-size: 1rem; } button { padding: 0.5rem 1rem; background-color: #4CAF50; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 1rem; transition: background-color 0.3s; } button:hover { background-color: #45a049; } footer { text-align: center; padding: 1rem; background-color: #333; color: white; border-radius: 5px; } media (max-width: 768px) { main { grid-template-columns: 1fr; } } EOF# 创建JavaScript文件catwww/js/script.jsEOF // 简单的交互脚本 document.addEventListener(DOMContentLoaded, function() { console.log(Simple HTTP Server page loaded); // 为表单添加提交事件监听 const forms document.querySelectorAll(form); forms.forEach(form { form.addEventListener(submit, async function(e) { if (form.method.toUpperCase() GET) { // GET请求让浏览器正常处理 return; } e.preventDefault(); const formData new FormData(form); const url form.action; try { const response await fetch(url, { method: POST, body: new URLSearchParams(formData) }); const data await response.json(); // 显示响应 alert(Response received:\n JSON.stringify(data, null, 2)); } catch (error) { console.error(Error:, error); alert(Error submitting form); } }); }); // 添加简单的点击效果 const buttons document.querySelectorAll(button); buttons.forEach(button { button.addEventListener(click, function() { this.style.transform scale(0.95); setTimeout(() { this.style.transform scale(1); }, 150); }); }); }); EOF# 创建测试页面catwww/test.htmlEOF !DOCTYPE html html head titleTest Page/title style body { font-family: Arial, sans-serif; margin: 40px; } .test-section { margin: 20px 0; padding: 20px; border: 1px solid #ddd; } pre { background: #f4f4f4; padding: 10px; overflow: auto; } /style /head body h1HTTP Server Test Page/h1 div classtest-section h21. Basic HTML/h2 pThis paragraph tests basic HTML rendering./p ul liList item 1/li liList item 2/li liList item 3/li /ul /div div classtest-section h22. Image Test/h2 pTest image loading (using placeholder):/p img srchttps://via.placeholder.com/150 altTest Image /div div classtest-section h23. Form Tests/h2 h3GET Form/h3 form action/api/data methodGET input typetext nametest valueget_test button typesubmitTest GET/button /form h3POST Form/h3 form action/api/data methodPOST input typetext nametest valuepost_test button typesubmitTest POST/button /form h3File Upload (multipart/form-data)/h3 form action/api/upload methodPOST enctypemultipart/form-data input typefile namefile button typesubmitUpload/button /form /div div classtest-section h24. JSON API Test/h2 button onclicktestAPI()Test API Status/button pre idapi-result/pre script async function testAPI() { try { const response await fetch(/api/status); const data await response.json(); document.getElementById(api-result).textContent JSON.stringify(data, null, 2); } catch (error) { document.getElementById(api-result).textContent Error: error.message; } } /script /div div classtest-section h25. Error Pages Test/h2 pTest error responses:/p a href/nonexistent.html404 Test/abr a href/../etc/passwd403 Test (directory traversal)/abr a href/api/nonexistentAPI 404 Test/a /div /body /html EOF# 创建JSON配置文件catwww/config.jsonEOF { server: { name: SimpleHTTPServer, version: 1.0.0, description: A simple HTTP server implementation in C }, features: [ Static file serving, Directory listing, JSON API endpoints, GET/POST form handling, Keep-alive connections, Non-blocking I/O, Event-driven architecture ], endpoints: { /api/status: Server status information, /api/data: Test data endpoint (GET/POST), /api/upload: File upload endpoint } } EOF编译和运行服务器# 编译make# 运行在后台运行./httpserver -p8080-d ./www# 测试服务器curlhttp://localhost:8080/curlhttp://localhost:8080/api/statuscurl-X POST http://localhost:8080/api/data -dnametestvalue123curlhttp://localhost:8080/test.html# 查看服务器日志如果有tail-f server.log# 停止服务器pkillhttpserver3.3 压力测试使用工具对服务器进行压力测试# 使用ab (Apache Benchmark) 进行压力测试ab -n10000-c100http://localhost:8080/# 使用wrk进行更高级的压力测试wrk -t12 -c400 -d30s http://localhost:8080/# 测试静态文件ab -n5000-c50http://localhost:8080/css/style.css# 测试API端点ab -n2000-c20-p post_data.txt -T application/x-www-form-urlencoded http://localhost:8080/api/data# post_data.txt内容# nametestvalue123四、GET/POST方法获取数据详解4.1 GET方法数据获取GET方法通过URL查询字符串传递数据数据附在URL之后以?分隔多个参数用连接。GET请求的特点数据在URL中可见安全性较低有长度限制浏览器和服务器都有限制可以被缓存、收藏、分享只应用于获取数据不应修改数据GET参数解析实现classGetRequestHandler{public:staticvoidhandle_get_request(constHttpRequestrequest,HttpResponseresponse){autoparamsrequest.get_query_params();if(params.empty()){// 没有参数返回简单响应response.set_status(200);response.set_body(h1GET Request Received/h1pNo parameters provided./p);return;}// 构建响应std::stringstream html;htmlhtmlheadtitleGET Parameters/title/head;htmlbodyh1GET Request Parameters/h1;htmltable border1 styleborder-collapse: collapse;;htmltrthParameter/ththValue/th/tr;for(constautoparam:params){htmltr;htmltdhtml_escape(param.first)/td;htmltdhtml_escape(param.second)/td;html/tr;}html/table;htmlpTotal parameters: params.size()/p;html/body/html;response.set_status(200);response.set_body(html.str());}staticstd::stringhtml_escape(conststd::stringstr){std::string result;result.reserve(str.length());for(charc:str){switch(c){case:result.append(amp;);break;case:result.append(lt;);break;case:result.append(gt;);break;case:result.append(quot;);break;case\:result.append(#39;);break;default:result.push_back(c);break;}}returnresult;}};4.2 POST方法数据获取POST方法通过请求体传递数据适合传输大量数据或敏感信息。POST请求的特点数据在请求体中相对安全没有长度限制实际受服务器配置限制不会被缓存可以用于创建、更新、删除数据POST参数解析实现classPostRequestHandler{public:staticvoidhandle_post_request(constHttpRequestrequest,HttpResponseresponse){autoform_datarequest.get_form_data();std::string content_typerequest.get_header(Content-Type);std::stringstream html;htmlhtmlheadtitlePOST Request/title/head;htmlbodyh1POST Request Received/h1;htmlpContent-Type: html_escape(content_type)/p;if(content_type.find(multipart/form-data)!std::string::npos){handle_multipart_data(request,html);}elseif(content_type.find(application/json)!std::string::npos){handle_json_data(request,html);}else{// application/x-www-form-urlencoded 或默认htmlh2Form Data/h2;htmltable border1 styleborder-collapse: collapse;;htmltrthField/ththValue/th/tr;for(constautodata:form_data){htmltr;htmltdhtml_escape(data.first)/td;htmltdhtml_escape(data.second)/td;html/tr;}html/table;htmlpTotal fields: form_data.size()/p;}html/body/html;response.set_status(200);response.set_body(html.str());}staticvoidhandle_multipart_data(constHttpRequestrequest,std::stringstreamhtml){htmlh2Multipart Form Data/h2;autoform_datarequest.get_form_data();htmltable border1 styleborder-collapse: collapse;;htmltrthField/ththValue Length/th/tr;for(constautodata:form_data){htmltr;htmltdhtml_escape(data.first)/td;htmltddata.second.length() bytes/td;html/tr;}html/table;// 原始请求体前200字节std::string bodyrequest.get_body();size_t preview_lenstd::min(body.length(),static_castsize_t(200));htmlh3Raw Body Preview (first preview_len bytes):/h3;htmlprehtml_escape(body.substr(0,preview_len))/pre;}staticvoidhandle_json_data(constHttpRequestrequest,std::stringstreamhtml){htmlh2JSON Data/h2;std::string bodyrequest.get_body();try{Json::Value json;Json::CharReaderBuilder reader;std::string errors;std::istringstreamjson_stream(body);if(Json::parseFromStream(reader,json_stream,json,errors)){htmlprehtml_escape(json.toStyledString())/pre;}else{htmlpInvalid JSON: html_escape(errors)/p;}}catch(conststd::exceptione){htmlpJSON parsing error: html_escape(e.what())/p;}}staticstd::stringhtml_escape(conststd::stringstr){std::string result;result.reserve(str.length());for(charc:str){switch(c){case:result.append(amp;);break;case:result.append(lt;);break;case:result.append(gt;);break;case:result.append(quot;);break;case\:result.append(#39;);break;default:result.push_back(c);break;}}returnresult;}};4.3 RESTful API设计示例基于GET/POST方法我们可以设计一个简单的RESTful APIclassUserAPI{private:// 简单的内存存储实际应用应该使用数据库std::mapint,Json::Valueusers;intnext_id;public:UserAPI():next_id(1){// 初始化一些测试数据add_test_users();}voidhandle_request(constHttpRequestrequest,HttpResponseresponse){std::string methodrequest.get_method();std::string pathrequest.get_uri();// 解析路径例如/api/users, /api/users/1std::vectorstd::stringparts;std::istringstreampath_stream(path);std::string part;while(std::getline(path_stream,part,/)){if(!part.empty()){parts.push_back(part);}}// 路由处理if(parts.size()2parts[0]apiparts[1]users){if(parts.size()2){// /api/usersif(methodGET){get_users(request,response);}elseif(methodPOST){create_user(request,response);}else{response.set_status(405);response.set_header(Allow,GET, POST);}}elseif(parts.size()3){// /api/users/{id}try{intidstd::stoi(parts[2]);if(methodGET){get_user(id,response);}elseif(methodPUT){update_user(id,request,response);}elseif(methodDELETE){delete_user(id,response);}else{response.set_status(405);response.set_header(Allow,GET, PUT, DELETE);}}catch(conststd::exceptione){responseHttpResponse::make_error_response(400,Invalid user ID);}}else{responseHttpResponse::make_error_response(404,Not Found);}}else{responseHttpResponse::make_error_response(404,Not Found);}}private:voidget_users(constHttpRequestrequest,HttpResponseresponse){Json::Valueresult(Json::arrayValue);for(constautopair:users){result.append(pair.second);}Json::StreamWriterBuilder writer;std::string json_strJson::writeString(writer,result);responseHttpResponse::make_json_response(json_str);}voidget_user(intid,HttpResponseresponse){autoitusers.find(id);if(itusers.end()){responseHttpResponse::make_error_response(404,User not found);return;}Json::StreamWriterBuilder writer;std::string json_strJson::writeString(writer,it-second);responseHttpResponse::make_json_response(json_str);}voidcreate_user(constHttpRequestrequest,HttpResponseresponse){std::string bodyrequest.get_body();try{Json::Value json;Json::CharReaderBuilder reader;std::string errors;std::istringstreamjson_stream(body);if(!Json::parseFromStream(reader,json_stream,json,errors)){responseHttpResponse::make_error_response(400,Invalid JSON: errors);return;}// 验证必需字段if(!json.isMember(name)||!json.isMember(email)){responseHttpResponse::make_error_response(400,Missing required fields);return;}// 创建新用户intidnext_id;json[id]id;json[created_at]static_castJson::UInt64(time(nullptr));users[id]json;// 返回创建的用户response.set_status(201);response.set_header(Location,/api/users/std::to_string(id));Json::StreamWriterBuilder writer;std::string json_strJson::writeString(writer,json);response.set_json_body(json_str);}catch(conststd::exceptione){responseHttpResponse::make_error_response(400,std::string(Error: )e.what());}}voidupdate_user(intid,constHttpRequestrequest,HttpResponseresponse){autoitusers.find(id);if(itusers.end()){responseHttpResponse::make_error_response(404,User not found);return;}std::string bodyrequest.get_body();try{Json::Value update_data;Json::CharReaderBuilder reader;std::string errors;std::istringstreamjson_stream(body);if(!Json::parseFromStream(reader,json_stream,update_data,errors)){responseHttpResponse::make_error_response(400,Invalid JSON: errors);return;}// 更新用户数据Json::Valueuserit-second;for(constautokey:update_data.getMemberNames()){// 不允许更新id和created_atif(key!idkey!created_at){user[key]update_data[key];}}user[updated_at]static_castJson::UInt64(time(nullptr));// 返回更新后的用户Json::StreamWriterBuilder writer;std::string json_strJson::writeString(writer,user);responseHttpResponse::make_json_response(json_str);}catch(conststd::exceptione){responseHttpResponse::make_error_response(400,std::string(Error: )e.what());}}voiddelete_user(intid,HttpResponseresponse){autoitusers.find(id);if(itusers.end()){responseHttpResponse::make_error_response(404,User not found);return;}users.erase(it);response.set_status(204);// No Content}voidadd_test_users(){for(inti1;i5;i){Json::Value user;user[id]i;user[name]User std::to_string(i);user[email]userstd::to_string(i)example.com;user[created_at]static_castJson::UInt64(time(nullptr)-i*86400);users[i]user;}next_id6;}};4.4 文件上传处理文件上传是POST方法的一个重要应用通常使用multipart/form-data格式classFileUploadHandler{public:staticvoidhandle_upload(constHttpRequestrequest,HttpResponseresponse){std::string content_typerequest.get_header(Content-Type);if(content_type.find(multipart/form-data)std::string::npos){responseHttpResponse::make_error_response(400,Content-Type must be multipart/form-data);return;}// 解析boundarysize_t boundary_poscontent_type.find(boundary);if(boundary_posstd::string::npos){responseHttpResponse::make_error_response(400,Missing boundary in Content-Type);return;}std::string boundarycontent_type.substr(boundary_pos9);std::string bodyrequest.get_body();// 创建上传目录std::string upload_diruploads;if(!fs::exists(upload_dir)){fs::create_directory(upload_dir);}std::vectorUploadedFilefilesparse_multipart(body,boundary,upload_dir);// 构建响应Json::Valueresult(Json::arrayValue);for(constautofile:files){Json::Value file_info;file_info[filename]file.filename;file_info[fieldname]file.fieldname;file_info[size]static_castJson::UInt64(file.size);file_info[path]file.path;file_info[content_type]file.content_type;result.append(file_info);}Json::StreamWriterBuilder writer;std::string json_strJson::writeString(writer,result);responseHttpResponse::make_json_response(json_str);}private:structUploadedFile{std::string filename;std::string fieldname;std::string path;std::string content_type;size_t size;};staticstd::vectorUploadedFileparse_multipart(conststd::stringbody,conststd::stringboundary,conststd::stringupload_dir){std::vectorUploadedFilefiles;std::string delimiter--boundary;std::string end_delimiterdelimiter--;size_t pos0;// 跳过第一个delimiterposbody.find(delimiter,pos);if(posstd::string::npos)returnfiles;posdelimiter.length();while(posbody.length()){// 跳过CRLFif(body.substr(pos,2)\r\n){pos2;}// 检查是否到达结束delimiterif(body.substr(pos,end_delimiter.length())end_delimiter){break;}// 解析part头部std::mapstd::string,std::stringpart_headers;while(posbody.length()){size_t line_endbody.find(\r\n,pos);if(line_endstd::string::npos)break;std::string linebody.substr(pos,line_end-pos);posline_end2;// 空行表示头部结束if(line.empty()){break;}size_t colon_posline.find(:);if(colon_pos!std::string::npos){std::string keyline.substr(0,colon_pos);std::string valueline.substr(colon_pos1);// 去除空白字符trim(key);trim(value);part_headers[key]value;}}// 查找part内容结束位置size_t part_endbody.find(\r\ndelimiter,pos);if(part_endstd::string::npos)break;std::string part_contentbody.substr(pos,part_end-pos);// 处理文件上传autocontent_disposition_itpart_headers.find(Content-Disposition);if(content_disposition_it!part_headers.end()){std::string dispositioncontent_disposition_it-second;// 解析Content-Dispositionstd::mapstd::string,std::stringdisposition_paramsparse_disposition_params(disposition);autofilename_itdisposition_params.find(filename);autoname_itdisposition_params.find(name);if(filename_it!disposition_params.end()name_it!disposition_params.end()){// 这是文件上传UploadedFile file;file.filenamefilename_it-second;file.fieldnamename_it-second;file.sizepart_content.size();// 获取Content-Typeautocontent_type_itpart_headers.find(Content-Type);if(content_type_it!part_headers.end()){file.content_typecontent_type_it-second;}else{file.content_typeapplication/octet-stream;}// 生成唯一文件名std::string unique_namegenerate_unique_filename(file.filename);file.pathupload_dir/unique_name;// 保存文件std::ofstreamout_file(file.path,std::ios::binary);if(out_file){out_file.write(part_content.data(),part_content.size());out_file.close();files.push_back(file);}}}pospart_end2;}returnfiles;}staticstd::mapstd::string,std::stringparse_disposition_params(conststd::stringdisposition){std::mapstd::string,std::stringparams;size_t pos0;while(posdisposition.length()){// 查找参数名size_t name_startdisposition.find_first_not_of( ;,pos);if(name_startstd::string::npos)break;size_t name_enddisposition.find(,name_start);if(name_endstd::string::npos)break;std::string namedisposition.substr(name_start,name_end-name_start);trim(name);// 查找参数值size_t value_startname_end1;if(value_startdisposition.length())break;if(disposition[value_start]){// 引号包围的值value_start;size_t value_enddisposition.find(,value_start);if(value_endstd::string::npos)break;std::string valuedisposition.substr(value_start,value_end-value_start);params[name]value;posvalue_end1;}else{// 无引号的值size_t value_enddisposition.find_first_of( ;,value_start);if(value_endstd::string::npos)value_enddisposition.length();std::string valuedisposition.substr(value_start,value_end-value_start);params[name]value;posvalue_end;}}returnparams;}staticstd::stringgenerate_unique_filename(conststd::stringoriginal_filename){// 提取扩展名size_t dot_posoriginal_filename.find_last_of(.);std::string extension;std::string basename;if(dot_pos!std::string::npos){basenameoriginal_filename.substr(0,dot_pos);extensionoriginal_filename.substr(dot_pos);}else{basenameoriginal_filename;}// 生成时间戳和随机数autonowstd::chrono::system_clock::now();autotimestampstd::chrono::duration_caststd::chrono::milliseconds(now.time_since_epoch()).count();std::random_device rd;std::mt19937gen(rd());std::uniform_int_distributiondis(1000,9999);intrandom_numdis(gen);// 构建唯一文件名std::stringstream ss;ssbasename_timestamp_random_numextension;returnss.str();}staticvoidtrim(std::stringstr){str.erase(str.begin(),std::find_if(str.begin(),str.end(),[](intch){return!std::isspace(ch);}));str.erase(std::find_if(str.rbegin(),str.rend(),[](intch){return!std::isspace(ch);}).base(),str.end());}};4.5 安全考虑处理GET/POST请求时需要考虑安全性classSecurityHandler{public:// 防止SQL注入staticstd::stringsanitize_sql_input(conststd::stringinput){// 这里应该使用参数化查询而不是字符串拼接// 这只是简单的示例std::string sanitizedinput;// 移除或转义特殊字符std::vectorstd::pairstd::string,std::stringreplacements{{,},{\,\\\},{\\,\\\\},{\0,},{\n,},{\r,},{\t,},{\b,},{\x1a,}// CtrlZ};for(constautorepl:replacements){size_t pos0;while((possanitized.find(repl.first,pos))!std::string::npos){sanitized.replace(pos,repl.first.length(),repl.second);posrepl.second.length();}}returnsanitized;}// 防止XSS攻击staticstd::stringsanitize_html_input(conststd::stringinput){std::string sanitizedinput;std::vectorstd::pairstd::string,std::stringreplacements{{,amp;},{,lt;},{,gt;},{\,quot;},{,#39;},{(,#40;},{),#41;},{/,#47;}};for(constautorepl:replacements){size_t pos0;while((possanitized.find(repl.first,pos))!std::string::npos){sanitized.replace(pos,repl.first.length(),repl.second);posrepl.second.length();}}returnsanitized;}// 验证输入长度staticboolvalidate_input_length(conststd::stringinput,size_t max_length255){returninput.length()max_length;}// 验证邮箱格式staticboolvalidate_email(conststd::stringemail){// 简单的邮箱验证size_t at_posemail.find();if(at_posstd::string::npos||at_pos0||at_posemail.length()-1){returnfalse;}size_t dot_posemail.find(.,at_pos);if(dot_posstd::string::npos||dot_posat_pos1||dot_posemail.length()-1){returnfalse;}// 检查非法字符for(charc:email){if(!isalnum(c)c!c!.c!_c!-){returnfalse;}}returntrue;}// 验证URLstaticboolvalidate_url(conststd::stringurl){// 简单的URL验证if(url.empty()||url.length()2083){// URL最大长度returnfalse;}// 检查协议if(url.find(http://)!0url.find(https://)!0){returnfalse;}// 检查非法字符for(charc:url){if(c32||c126){// 可打印ASCII字符returnfalse;}}returntrue;}// 防止CSRF攻击简化版staticboolvalidate_csrf_token(constHttpRequestrequest,conststd::stringexpected_token){// 从表单数据或请求头中获取tokenstd::string tokenrequest.get_form_data(csrf_token);if(token.empty()){tokenrequest.get_header(X-CSRF-Token);}return!token.empty()tokenexpected_token;}// 生成CSRF令牌staticstd::stringgenerate_csrf_token(){std::random_device rd;std::mt19937_64gen(rd());std::uniform_int_distributionuint64_tdis;std::stringstream ss;ssstd::hexdis(gen)dis(gen);returnss.str();}// 防止目录遍历攻击staticboolis_safe_path(conststd::stringpath,conststd::stringbase_dir){fs::path requested_pathfs::absolute(fs::path(base_dir)/path);fs::path base_pathfs::absolute(base_dir);// 检查请求路径是否在基础目录内autoitrequested_path.begin();autobase_itbase_path.begin();while(base_it!base_path.end()){if(itrequested_path.end()||*it!*base_it){returnfalse;}it;base_it;}returntrue;}};五、扩展功能与优化5.1 支持HTTPS为服务器添加HTTPS支持需要集成SSL/TLS#ifdefUSE_OPENSSL#includeopenssl/ssl.h#includeopenssl/err.hclassHttpsServer{private:SSL_CTX*ssl_ctx;public:HttpsServer():ssl_ctx(nullptr){}~HttpsServer(){if(ssl_ctx){SSL_CTX_free(ssl_ctx);}}boolinit_ssl(conststd::stringcert_file,conststd::stringkey_file){// 初始化OpenSSLSSL_load_error_strings();OpenSSL_add_ssl_algorithms();// 创建SSL上下文ssl_ctxSSL_CTX_new(TLS_server_method());if(!ssl_ctx){ERR_print_errors_fp(stderr);returnfalse;}// 加载证书和私钥if(SSL_CTX_use_certificate_file(ssl_ctx,cert_file.c_str(),SSL_FILETYPE_PEM)0){ERR_print_errors_fp(stderr);returnfalse;}if(SSL_CTX_use_PrivateKey_file(ssl_ctx,key_file.c_str(),SSL_FILETYPE_PEM)0){ERR_print_errors_fp(stderr);returnfalse;}// 验证私钥匹配证书if(!SSL_CTX_check_private_key(ssl_ctx)){fprintf(stderr,Private key does not match the certificate\n);returnfalse;}returntrue;}SSL*create_ssl(intclient_fd){SSL*sslSSL_new(ssl_ctx);SSL_set_fd(ssl,client_fd);if(SSL_accept(ssl)0){ERR_print_errors_fp(stderr);SSL_free(ssl);returnnullptr;}returnssl;}};classSslConnection:publicConnection{private:SSL*ssl;public:SslConnection(intfd,Reactor*reactor,conststructsockaddr_inaddr,SSL*ssl_obj):Connection(fd,reactor,addr),ssl(ssl_obj){}~SslConnection(){if(ssl){SSL_shutdown(ssl);SSL_free(ssl);}}protected:ssize_tssl_read(char*buffer,size_t size){returnSSL_read(ssl,buffer,size);}ssize_tssl_write(constchar*buffer,size_t size){returnSSL_write(ssl,buffer,size);}};#endif5.2 缓存支持添加HTTP缓存支持以提高性能classCacheManager{private:structCacheEntry{std::string content;std::string content_type;std::time_t timestamp;std::time_t expires;std::string etag;boolis_expired()const{returnstd::time(nullptr)expires;}std::stringget_last_modified()const{charbuf[100];std::strftime(buf,sizeof(buf),%a, %d %b %Y %H:%M:%S GMT,std::gmtime(timestamp));returnbuf;}};std::mapstd::string,CacheEntrycache;size_t max_size;size_t current_size;public:CacheManager(size_t max_cache_size100*1024*1024)// 100MB:max_size(max_cache_size),current_size(0){}boolget(conststd::stringkey,CacheEntryentry){autoitcache.find(key);if(itcache.end()){returnfalse;}if(it-second.is_expired()){// 缓存过期移除current_size-it-second.content.size();cache.erase(it);returnfalse;}entryit-second;returntrue;}voidset(conststd::stringkey,conststd::stringcontent,conststd::stringcontent_type,intttl_seconds3600){// 检查是否已存在autoitcache.find(key);if(it!cache.end()){current_size-it-second.content.size();}// 检查缓存大小限制if(current_sizecontent.size()max_size){// 移除一些旧缓存cleanup_old_entries();}if(current_sizecontent.size()max_size){// 仍然太大不缓存return;}// 生成ETag简化版std::string etaggenerate_etag(content);CacheEntry entry;entry.contentcontent;entry.content_typecontent_type;entry.timestampstd::time(nullptr);entry.expiresentry.timestampttl_seconds;entry.etagetag;cache[key]entry;current_sizecontent.size();}voidinvalidate(conststd::stringkey){autoitcache.find(key);if(it!cache.end()){current_size-it-second.content.size();cache.erase(it);}}voidcleanup_old_entries(){std::time_t nowstd::time(nullptr);std::vectorstd::stringto_remove;for(constautopair:cache){if(pair.second.is_expired()){to_remove.push_back(pair.first);}}for(constautokey:to_remove){autoitcache.find(key);if(it!cache.end()){current_size-it-second.content.size();cache.erase(it);}}}private:std::stringgenerate_etag(conststd::stringcontent){// 简化版的ETag生成std::hashstd::stringhasher;size_t hashhasher(content);std::stringstream ss;ss\std::hexhash\;returnss.str();}};classCachingHttpHandler{private:CacheManager cache;public:boolhandle_request_with_cache(constHttpRequestrequest,HttpResponseresponse){std::string cache_keyrequest.get_uri();// 检查缓存CacheManager::CacheEntry cached;if(cache.get(cache_key,cached)){// 检查条件请求if(handle_conditional_request(request,cached,response)){returntrue;}// 返回缓存的响应response.set_status(200);response.set_body(cached.content,cached.content_type);response.set_header(ETag,cached.etag);response.set_header(Last-Modified,cached.get_last_modified());response.set_header(Cache-Control,public, max-age3600);returntrue;}returnfalse;}voidcache_response(conststd::stringkey,constHttpResponseresponse){// 只缓存成功的GET响应if(response.get_status()200){std::string contentresponse.get_body();std::string content_typeresponse.get_header(Content-Type);cache.set(key,content,content_type);}}private:boolhandle_conditional_request(constHttpRequestrequest,constCacheManager::CacheEntrycached,HttpResponseresponse){// 检查If-None-Matchstd::string if_none_matchrequest.get_header(If-None-Match);if(!if_none_match.empty()if_none_matchcached.etag){response.set_status(304);// Not Modifiedresponse.set_header(ETag,cached.etag);response.set_header(Cache-Control,public, max-age3600);returntrue;}// 检查If-Modified-Sincestd::string if_modified_sincerequest.get_header(If-Modified-Since);if(!if_modified_since.empty()){// 解析时间简化处理std::tm tm{};std::istringstreamss(if_modified_since);ssstd::get_time(tm,%a, %d %b %Y %H:%M:%S GMT);if(!ss.fail()){std::time_t modified_sincestd::mktime(tm);if(cached.timestampmodified_since){response.set_status(304);// Not Modifiedresponse.set_header(ETag,cached.etag);response.set_header(Cache-Control,public, max-age3600);returntrue;}}}returnfalse;}};5.3 日志系统实现一个完整的日志系统classLogger{public:enumLogLevel{DEBUG,INFO,WARNING,ERROR,FATAL};staticLoggerget_instance(){staticLogger instance;returninstance;}voidinit(conststd::stringlog_file,LogLevel min_levelINFO){std::lock_guardstd::mutexlock(mutex_);if(file_.is_open()){file_.close();}file_.open(log_file,std::ios::app);min_level_min_level;initialized_true;}voidlog(LogLevel level,conststd::stringmessage,constchar*filenullptr,intline0){if(levelmin_level_||!initialized_){return;}std::lock_guardstd::mutexlock(mutex_);std::time_t nowstd::time(nullptr);chartime_buf[100];std::strftime(time_buf,sizeof(time_buf),%Y-%m-%d %H:%M:%S,std::localtime(now));std::string level_str;switch(level){caseDEBUG:level_strDEBUG;break;caseINFO:level_strINFO;break;caseWARNING:level_strWARNING;break;caseERROR:level_strERROR;break;caseFATAL:level_strFATAL;break;}std::stringstream ss;ss[time_buf] [level_str] ;if(file){ss[file:line] ;}ssmessagestd::endl;std::string log_liness.str();// 输出到文件if(file_.is_open()){file_log_line;file_.flush();}// 输出到控制台std::coutlog_line;}private:Logger():min_level_(INFO),initialized_(false){}~Logger(){if(file_.is_open()){file_.close();}}Logger(constLogger)delete;Loggeroperator(constLogger)delete;std::ofstream file_;LogLevel min_level_;boolinitialized_;std::mutex mutex_;};// 宏定义方便使用#defineLOG_DEBUG(msg)Logger::get_instance().log(Logger::DEBUG,msg,__FILE__,__LINE__)#defineLOG_INFO(msg)Logger::get_instance().log(Logger::INFO,msg,__FILE__,__LINE__)#defineLOG_WARNING(msg)Logger::get_instance().log(Logger::WARNING,msg,__FILE__,__LINE__)#defineLOG_ERROR(msg)Logger::get_instance().log(Logger::ERROR,msg,__FILE__,__LINE__)#defineLOG_FATAL(msg)Logger::get_instance().log(Logger::FATAL,msg,__FILE__,__LINE__)// HTTP访问日志classAccessLogger{public:voidlog_request(constHttpRequestrequest,constHttpResponseresponse,conststructsockaddr_inclient_addr,longresponse_time_ms){std::stringstream ss;// 客户端IPcharip_str[INET_ADDRSTRLEN];inet_ntop(AF_INET,client_addr.sin_addr,ip_str,sizeof(ip_str));// 时间戳std::time_t nowstd::time(nullptr);chartime_buf[100];std::strftime(time_buf,sizeof(time_buf),%d/%b/%Y:%H:%M:%S %z,std::localtime(now));// 请求行std::string request_linerequest.get_method() request.get_uri() request.get_version();// 用户代理std::string user_agentrequest.get_header(User-Agent);if(user_agent.empty())user_agent-;// Refererstd::string refererrequest.get_header(Referer);if(referer.empty())referer-;// 构建日志行Common Log Formatssip_str - - [time_buf] \request_line\ response.get_status() response.get_body().size() \referer\ \user_agent\ response_time_msms;LOG_INFO(ss.str());}};5.4 配置管理实现配置文件管理classConfig{private:std::mapstd::string,std::stringsettings;public:boolload(conststd::stringfilename){std::ifstreamfile(filename);if(!file){LOG_ERROR(Cannot open config file: filename);returnfalse;}std::string line;intline_num0;while(std::getline(file,line)){line_num;// 去除注释size_t comment_posline.find(#);if(comment_pos!std::string::npos){lineline.substr(0,comment_pos);}// 去除空白字符trim(line);// 跳过空行if(line.empty()){continue;}// 解析键值对size_t eq_posline.find();if(eq_posstd::string::npos){LOG_WARNING(Invalid config line std::to_string(line_num): line);continue;}std::string keyline.substr(0,eq_pos);std::string valueline.substr(eq_pos1);trim(key);trim(value);// 去除值的引号if(!value.empty()){if((value.front()value.back())||(value.front()\value.back()\)){valuevalue.substr(1,value.length()-2);}}settings[key]value;}LOG_INFO(Loaded std::to_string(settings.size()) settings from filename);returntrue;}std::stringget_string(conststd::stringkey,conststd::stringdefault_value){autoitsettings.find(key);returnit!settings.end()?it-second:default_value;}intget_int(conststd::stringkey,intdefault_value0){autoitsettings.find(key);if(it!settings.end()){try{returnstd::stoi(it-second);}catch(conststd::exceptione){LOG_ERROR(Invalid integer value for key: it-second);}}returndefault_value;}boolget_bool(conststd::stringkey,booldefault_valuefalse){autoitsettings.find(key);if(it!settings.end()){std::string valueit-second;std::transform(value.begin(),value.end(),value.begin(),::tolower);if(valuetrue||valueyes||value1){returntrue;}elseif(valuefalse||valueno||value0){returnfalse;}}returndefault_value;}private:voidtrim(std::stringstr){str.erase(str.begin(),std::find_if(str.begin(),str.end(),[](intch){return!std::isspace(ch);}));str.erase(std::find_if(str.rbegin(),str.rend(),[](intch){return!std::isspace(ch);}).base(),str.end());}};// 配置文件示例 (server.conf)/* # HTTP Server Configuration # Server settings server.port 8080 server.address 0.0.0.0 server.root_dir ./www server.thread_pool_size 4 server.max_connections 1000 # Logging log.file server.log log.level INFO log.access_log true # Security security.max_request_size 10485760 # 10MB security.enable_cors true security.cors_origins * # Cache cache.enabled true cache.max_size 100000000 # 100MB cache.default_ttl 3600 # Performance performance.send_buffer_size 8192 performance.recv_buffer_size 8192 performance.keep_alive_timeout 15 */六、性能优化建议6.1 连接池管理classConnectionPool{private:std::queueintavailable_connections;std::setintused_connections;std::mutex mutex_;std::condition_variable cv_;intmax_size;public:ConnectionPool(intmax_pool_size100):max_size(max_pool_size){// 预创建连接for(inti0;imax_pool_size/2;i){intfdcreate_connection();if(fd0){available_connections.push(fd);}}}~ConnectionPool(){std::lock_guardstd::mutexlock(mutex_);while(!available_connections.empty()){close(available_connections.front());available_connections.pop();}for(intfd:used_connections){close(fd);}}intacquire(){std::unique_lockstd::mutexlock(mutex_);// 等待可用连接cv_.wait(lock,[this]{return!available_connections.empty()||used_connections.size()max_size;});if(!available_connections.empty()){intfdavailable_connections.front();available_connections.pop();used_connections.insert(fd);returnfd;}else{// 创建新连接intfdcreate_connection();if(fd0){used_connections.insert(fd);}returnfd;}}voidrelease(intfd){std::lock_guardstd::mutexlock(mutex_);if(used_connections.erase(fd)0){// 检查连接是否仍然有效if(is_connection_valid(fd)){available_connections.push(fd);}else{close(fd);}cv_.notify_one();}}private:intcreate_connection(){// 创建新连接的具体实现// 这里简化处理returnsocket(AF_INET,SOCK_STREAM,0);}boolis_connection_valid(intfd){// 检查连接是否仍然有效charbuf[1];ssize_t nrecv(fd,buf,sizeof(buf),MSG_PEEK|MSG_DONTWAIT);if(n0){returnfalse;// 连接已关闭}elseif(n0){if(errno!EAGAINerrno!EWOULDBLOCK){returnfalse;// 错误}}returntrue;}};6.2 内存池优化classMemoryPool{private:structBlock{void*memory;size_t size;boolin_use;};std::vectorBlockblocks;size_t block_size;size_t max_blocks;public:MemoryPool(size_t block_size4096,size_t max_blocks1000):block_size(block_size),max_blocks(max_blocks){}~MemoryPool(){for(autoblock:blocks){if(block.memory){free(block.memory);}}}void*allocate(size_t size){if(sizeblock_size){// 大块内存直接分配returnmalloc(size);}// 查找空闲块for(autoblock:blocks){if(!block.in_use){block.in_usetrue;returnblock.memory;}}// 创建新块if(blocks.size()max_blocks){Block new_block;new_block.memorymalloc(block_size);new_block.sizeblock_size;new_block.in_usetrue;blocks.push_back(new_block);returnnew_block.memory;}// 池已满直接分配returnmalloc(size);}voiddeallocate(void*ptr){// 查找对应的块for(autoblock:blocks){if(block.memoryptr){block.in_usefalse;return;}}// 不是在池中分配的直接释放free(ptr);}size_tget_used_memory()const{size_t used0;for(constautoblock:blocks){if(block.in_use){usedblock.size;}}returnused;}};6.3 零拷贝技术// 使用sendfile实现零拷贝文件传输boolsend_file_zero_copy(intclient_fd,conststd::stringfilepath){intfile_fdopen(filepath.c_str(),O_RDONLY);if(file_fd0){returnfalse;}// 获取文件大小structstatfile_stat;if(fstat(file_fd,file_stat)0){close(file_fd);returnfalse;}off_t offset0;size_t remainingfile_stat.st_size;// 使用sendfile传输文件while(remaining0){ssize_t sentsendfile(client_fd,file_fd,offset,remaining);if(sent0){if(errnoEAGAIN||errnoEWOULDBLOCK){continue;}close(file_fd);returnfalse;}remaining-sent;}close(file_fd);returntrue;}// 使用writev实现向量化I/Oboolsend_response_vectorized(intclient_fd,constHttpResponseresponse){// 构建响应std::string status_lineresponse.get_version() std::to_string(response.get_status()) response.get_status_message()\r\n;std::string headers_str;for(constautoheader:response.get_headers()){headers_strheader.first: header.second\r\n;}headers_str\r\n;std::string bodyresponse.get_body();// 使用iovec数组structioveciov[3];iov[0].iov_base(void*)status_line.c_str();iov[0].iov_lenstatus_line.length();iov[1].iov_base(void*)headers_str.c_str();iov[1].iov_lenheaders_str.length();iov[2].iov_base(void*)body.c_str();iov[2].iov_lenbody.length();ssize_t total_sent0;ssize_t to_sendiov[0].iov_leniov[1].iov_leniov[2].iov_len;while(total_sentto_send){ssize_t sentwritev(client_fd,iov,3);if(sent0){if(errnoEAGAIN||errnoEWOULDBLOCK){continue;}returnfalse;}total_sentsent;// 更新iovecwhile(sent0){if(iov[0].iov_lensent){sent-iov[0].iov_len;iov[0].iov_len0;iov[0].iov_basenullptr;}else{iov[0].iov_base(char*)iov[0].iov_basesent;iov[0].iov_len-sent;sent0;}// 移动到下一个iovecif(iov[0].iov_len0iov[1].iov_len0){iov[0]iov[1];iov[1]iov[2];iov[2].iov_len0;iov[2].iov_basenullptr;}}}returntrue;}七、测试与验证7.1 单元测试#includegtest/gtest.h// HTTP请求解析测试TEST(HttpRequestTest,ParseSimpleGet){std::string raw_requestGET /index.html HTTP/1.1\r\nHost: localhost:8080\r\nUser-Agent: TestClient\r\n\r\n;HttpRequest request;boolsuccessrequest.parse(raw_request);ASSERT_TRUE(success);EXPECT_EQ(request.get_method(),GET);EXPECT_EQ(request.get_uri(),/index.html);EXPECT_EQ(request.get_version(),HTTP/1.1);EXPECT_EQ(request.get_header(Host),localhost:8080);EXPECT_EQ(request.get_header(User-Agent),TestClient);}TEST(HttpRequestTest,ParseGetWithQuery){std::string raw_requestGET /search?qhellopage1 HTTP/1.1\r\nHost: example.com\r\n\r\n;HttpRequest request;boolsuccessrequest.parse(raw_request);ASSERT_TRUE(success);EXPECT_EQ(request.get_uri(),/search);EXPECT_EQ(request.get_query_param(q),hello);EXPECT_EQ(request.get_query_param(page),1);}TEST(HttpRequestTest,ParsePostWithBody){std::string raw_requestPOST /submit HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 19\r\n\r\nnameJohnage30;HttpRequest request;boolsuccessrequest.parse(raw_request);ASSERT_TRUE(success);EXPECT_EQ(request.get_method(),POST);EXPECT_EQ(request.get_form_data(name),John);EXPECT_EQ(request.get_form_data(age),30);}// HTTP响应构建测试TEST(HttpResponseTest,BuildSimpleResponse){HttpResponse response;response.set_status(200);response.set_body(Hello World);std::string resultresponse.build();EXPECT_TRUE(result.find(HTTP/1.1 200 OK)!std::string::npos);EXPECT_TRUE(result.find(Content-Length: 11)!std::string::npos);EXPECT_TRUE(result.find(\r\n\r\nHello World)!std::string::npos);}TEST(HttpResponseTest,BuildJsonResponse){HttpResponse responseHttpResponse::make_json_response({\status\:\ok\});std::string resultresponse.build();EXPECT_TRUE(result.find(HTTP/1.1 200 OK)!std::string::npos);EXPECT_TRUE(result.find(Content-Type: application/json)!std::string::npos);EXPECT_TRUE(result.find({\status\:\ok\})!std::string::npos);}// URL解析测试TEST(UrlParserTest,ParseFullUrl){URL url;url.parse(https://www.example.com:8080/path/to/resource?keyvalue#fragment);EXPECT_EQ(url.get_scheme(),https);EXPECT_EQ(url.get_host(),www.example.com);EXPECT_EQ(url.get_port(),8080);EXPECT_EQ(url.get_path(),/path/to/resource);EXPECT_EQ(url.get_query_param(key),value);EXPECT_EQ(url.get_fragment(),fragment);}TEST(UrlParserTest,ParseRelativeUrl){URL url;url.parse(/api/users?page2);EXPECT_EQ(url.get_scheme(),);EXPECT_EQ(url.get_host(),);EXPECT_EQ(url.get_path(),/api/users);EXPECT_EQ(url.get_query_param(page),2);}// 安全功能测试TEST(SecurityTest,HtmlEscape){std::string inputscriptalert(xss)/script;std::string escapedSecurityHandler::sanitize_html_input(input);EXPECT_EQ(escaped,lt;scriptgt;alert(#39;xss#39;)lt;/scriptgt;);}TEST(SecurityTest,EmailValidation){EXPECT_TRUE(SecurityHandler::validate_email(userexample.com));EXPECT_TRUE(SecurityHandler::validate_email(john.doecompany.co.uk));EXPECT_FALSE(SecurityHandler::validate_email(invalid-email));EXPECT_FALSE(SecurityHandler::validate_email(example.com));EXPECT_FALSE(SecurityHandler::validate_email(user.com));}// 缓存测试TEST(CacheTest,BasicCacheOperations){CacheManagercache(1024);// 1KB缓存// 测试设置和获取cache.set(key1,value1,text/plain,60);CacheManager::CacheEntry entry;boolfoundcache.get(key1,entry);EXPECT_TRUE(found);EXPECT_EQ(entry.content,value1);EXPECT_EQ(entry.content_type,text/plain);// 测试过期cache.set(key2,value2,text/plain,-1);// 立即过期foundcache.get(key2,entry);EXPECT_FALSE(found);// 测试失效cache.set(key3,value3,text/plain,60);cache.invalidate(key3);foundcache.get(key3,entry);EXPECT_FALSE(found);}intmain(intargc,char**argv){::testing::InitGoogleTest(argc,argv);returnRUN_ALL_TESTS();}7.2 集成测试classHttpServerIntegrationTest{public:voidrun_all_tests(){test_server_startup();test_static_file_serving();test_api_endpoints();test_concurrent_requests();test_error_handling();test_performance();}private:voidtest_server_startup(){std::coutTesting server startup...std::endl;// 启动测试服务器HttpServerserver(0);// 使用随机端口ASSERT_TRUE(server.init());std::threadserver_thread([server](){server.start();});// 给服务器时间启动std::this_thread::sleep_for(std::chrono::milliseconds(100));// 测试连接intclient_fdsocket(AF_INET,SOCK_STREAM,0);ASSERT_GE(client_fd,0);structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_porthtons(server.get_port());inet_pton(AF_INET,127.0.0.1,server_addr.sin_addr);intresultconnect(client_fd,(structsockaddr*)server_addr,sizeof(server_addr));ASSERT_GE(result,0);close(client_fd);// 停止服务器server.stop();server_thread.join();std::cout✓ Server startup test passedstd::endl;}voidtest_static_file_serving(){std::coutTesting static file serving...std::endl;// 创建测试文件std::ofstreamtest_file(test_file.txt);test_fileHello, World!;test_file.close();// 启动服务器HttpServerserver(0);server.set_root_dir(.);ASSERT_TRUE(server.init());std::threadserver_thread([server](){server.start();});std::this_thread::sleep_for(std::chrono::milliseconds(100));// 发送HTTP请求intclient_fdsocket(AF_INET,SOCK_STREAM,0);structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_porthtons(server.get_port());inet_pton(AF_INET,127.0.0.1,server_addr.sin_addr);connect(client_fd,(structsockaddr*)server_addr,sizeof(server_addr));std::string requestGET /test_file.txt HTTP/1.1\r\nHost: localhost\r\n\r\n;write(client_fd,request.c_str(),request.length());// 读取响应charbuffer[4096];ssize_t nread(client_fd,buffer,sizeof(buffer)-1);buffer[n]\0;std::stringresponse(buffer);// 验证响应ASSERT_TRUE(response.find(HTTP/1.1 200 OK)!std::string::npos);ASSERT_TRUE(response.find(Hello, World!)!std::string::npos);close(client_fd);server.stop();server_thread.join();// 清理remove(test_file.txt);std::cout✓ Static file serving test passedstd::endl;}voidtest_api_endpoints(){std::coutTesting API endpoints...std::endl;HttpServerserver(0);ASSERT_TRUE(server.init());std::threadserver_thread([server](){server.start();});std::this_thread::sleep_for(std::chrono::milliseconds(100));// 测试GET请求test_http_request(server.get_port(),GET,/api/status,,[](conststd::stringresponse){returnresponse.find(\status\:\ok\)!std::string::npos;});// 测试POST请求std::string post_datanameTestvalue123;test_http_request(server.get_port(),POST,/api/data,post_data,[](conststd::stringresponse){returnresponse.find(\method\:\POST\)!std::string::nposresponse.find(\form_data\)!std::string::npos;});server.stop();server_thread.join();std::cout✓ API endpoints test passedstd::endl;}voidtest_http_request(intport,conststd::stringmethod,conststd::stringpath,conststd::stringbody,std::functionbool(conststd::string)validator){intclient_fdsocket(AF_INET,SOCK_STREAM,0);structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_porthtons(port);inet_pton(AF_INET,127.0.0.1,server_addr.sin_addr);connect(client_fd,(structsockaddr*)server_addr,sizeof(server_addr));std::stringstream request;requestmethod path HTTP/1.1\r\n;requestHost: localhost\r\n;if(!body.empty()){requestContent-Type: application/x-www-form-urlencoded\r\n;requestContent-Length: body.length()\r\n;}request\r\n;requestbody;std::string request_strrequest.str();write(client_fd,request_str.c_str(),request_str.length());charbuffer[4096];ssize_t nread(client_fd,buffer,sizeof(buffer)-1);buffer[n]\0;std::stringresponse(buffer);ASSERT_TRUE(validator(response));close(client_fd);}voidtest_concurrent_requests(){std::coutTesting concurrent requests...std::endl;HttpServerserver(0);server.set_thread_pool_size(4);ASSERT_TRUE(server.init());std::threadserver_thread([server](){server.start();});std::this_thread::sleep_for(std::chrono::milliseconds(100));constintnum_threads10;constintrequests_per_thread100;std::vectorstd::threadthreads;std::atomicintsuccess_count{0};autoworker[,portserver.get_port()](){for(inti0;irequests_per_thread;i){if(send_test_request(port)){success_count;}}};// 启动多个线程并发发送请求for(inti0;inum_threads;i){threads.emplace_back(worker);}// 等待所有线程完成for(autothread:threads){thread.join();}inttotal_requestsnum_threads*requests_per_thread;doublesuccess_ratestatic_castdouble(success_count)/total_requests*100;std::cout Success rate: success_rate% (success_count/total_requests)std::endl;ASSERT_GE(success_rate,95.0);// 至少95%的成功率server.stop();server_thread.join();std::cout✓ Concurrent requests test passedstd::endl;}boolsend_test_request(intport){intclient_fdsocket(AF_INET,SOCK_STREAM,0);if(client_fd0)returnfalse;structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_porthtons(port);inet_pton(AF_INET,127.0.0.1,server_addr.sin_addr);// 设置连接超时structtimevaltimeout;timeout.tv_sec1;timeout.tv_usec0;setsockopt(client_fd,SOL_SOCKET,SO_RCVTIMEO,timeout,sizeof(timeout));setsockopt(client_fd,SOL_SOCKET,SO_SNDTIMEO,timeout,sizeof(timeout));if(connect(client_fd,(structsockaddr*)server_addr,sizeof(server_addr))0){close(client_fd);returnfalse;}std::string requestGET /api/status HTTP/1.1\r\nHost: localhost\r\n\r\n;if(write(client_fd,request.c_str(),request.length())0){close(client_fd);returnfalse;}charbuffer[1024];ssize_t nread(client_fd,buffer,sizeof(buffer)-1);close(client_fd);if(n0)returnfalse;buffer[n]\0;std::stringresponse(buffer);returnresponse.find(HTTP/1.1)!std::string::npos;}voidtest_error_handling(){std::coutTesting error handling...std::endl;HttpServerserver(0);ASSERT_TRUE(server.init());std::threadserver_thread([server](){server.start();});std::this_thread::sleep_for(std::chrono::milliseconds(100));// 测试404错误test_error_response(server.get_port(),/nonexistent,404);// 测试400错误无效请求send_malformed_request(server.get_port());// 测试413错误请求体过大test_large_request(server.get_port());server.stop();server_thread.join();std::cout✓ Error handling test passedstd::endl;}voidtest_error_response(intport,conststd::stringpath,intexpected_code){intclient_fdsocket(AF_INET,SOCK_STREAM,0);structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_porthtons(port);inet_pton(AF_INET,127.0.0.1,server_addr.sin_addr);connect(client_fd,(structsockaddr*)server_addr,sizeof(server_addr));std::string requestGET path HTTP/1.1\r\nHost: localhost\r\n\r\n;write(client_fd,request.c_str(),request.length());charbuffer[4096];ssize_t nread(client_fd,buffer,sizeof(buffer)-1);buffer[n]\0;std::stringresponse(buffer);std::string expected_statusHTTP/1.1 std::to_string(expected_code);ASSERT_TRUE(response.find(expected_status)!std::string::npos);close(client_fd);}voidsend_malformed_request(intport){intclient_fdsocket(AF_INET,SOCK_STREAM,0);structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_porthtons(port);inet_pton(AF_INET,127.0.0.1,server_addr.sin_addr);connect(client_fd,(structsockaddr*)server_addr,sizeof(server_addr));// 发送无效的HTTP请求std::string bad_requestINVALID REQUEST LINE\r\n\r\n;write(client_fd,bad_request.c_str(),bad_request.length());charbuffer[4096];read(client_fd,buffer,sizeof(buffer)-1);close(client_fd);}voidtest_large_request(intport){intclient_fdsocket(AF_INET,SOCK_STREAM,0);structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_porthtons(port);inet_pton(AF_INET,127.0.0.1,server_addr.sin_addr);connect(client_fd,(structsockaddr*)server_addr,sizeof(server_addr));// 发送非常大的请求头std::stringstream request;requestPOST /api/data HTTP/1.1\r\n;requestHost: localhost\r\n;requestContent-Type: application/x-www-form-urlencoded\r\n;// 生成非常大的内容长度requestContent-Length: 1000000000\r\n;// 1GBrequest\r\n;// 开始发送数据但不会发送全部std::string request_strrequest.str();write(client_fd,request_str.c_str(),request_str.length());// 服务器应该会关闭连接或返回错误charbuffer[1024];ssize_t nread(client_fd,buffer,sizeof(buffer)-1);if(n0){buffer[n]\0;std::stringresponse(buffer);// 可能返回413或直接关闭连接}close(client_fd);}voidtest_performance(){std::coutTesting performance...std::endl;HttpServerserver(0);server.set_thread_pool_size(8);ASSERT_TRUE(server.init());std::threadserver_thread([server](){server.start();});std::this_thread::sleep_for(std::chrono::milliseconds(200));intportserver.get_port();// 使用多个客户端进行压力测试autostart_timestd::chrono::high_resolution_clock::now();constinttotal_requests10000;constintconcurrent_clients100;std::vectorstd::futureintfutures;std::atomicinttotal_processed{0};autoclient_func[,port](intclient_id,intrequests)-int{intprocessed0;for(inti0;irequests;i){if(send_simple_request(port)){processed;total_processed;}// 显示进度if((client_id0)(i%1000)){std::cout\r Progress: total_processed/total_requests;std::cout.flush();}}returnprocessed;};// 分配请求给各个客户端intrequests_per_clienttotal_requests/concurrent_clients;intremainingtotal_requests%concurrent_clients;for(inti0;iconcurrent_clients;i){intrequestsrequests_per_client(iremaining?1:0);futures.push_back(std::async(std::launch::async,client_func,i,requests));}// 等待所有客户端完成inttotal_success0;for(autofuture:futures){total_successfuture.get();}autoend_timestd::chrono::high_resolution_clock::now();autodurationstd::chrono::duration_caststd::chrono::milliseconds(end_time-start_time);doublerequests_per_secondtotal_requests*1000.0/duration.count();doublesuccess_ratetotal_success*100.0/total_requests;std::cout\n Duration: duration.count()msstd::endl;std::cout Requests per second: requests_per_secondstd::endl;std::cout Success rate: success_rate%std::endl;server.stop();server_thread.join();ASSERT_GE(success_rate,95.0);std::cout✓ Performance test passedstd::endl;}boolsend_simple_request(intport){intclient_fdsocket(AF_INET,SOCK_STREAM,0);if(client_fd0)returnfalse;structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_porthtons(port);inet_pton(AF_INET,127.0.0.1,server_addr.sin_addr);// 非阻塞连接intflagsfcntl(client_fd,F_GETFL,0);fcntl(client_fd,F_SETFL,flags|O_NONBLOCK);connect(client_fd,(structsockaddr*)server_addr,sizeof(server_addr));// 使用poll等待连接完成structpollfdpfd;pfd.fdclient_fd;pfd.eventsPOLLOUT;intretpoll(pfd,1,1000);// 1秒超时if(ret0){close(client_fd);returnfalse;}// 发送请求std::string requestGET /api/status HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n;if(write(client_fd,request.c_str(),request.length())0){close(client_fd);returnfalse;}// 接收响应charbuffer[1024];ssize_t nread(client_fd,buffer,sizeof(buffer)-1);close(client_fd);returnn0;}};7.3 性能基准测试classBenchmark{public:structResult{longtotal_requests;longsuccessful_requests;longfailed_requests;doublerequests_per_second;doubleaverage_latency_ms;doublep50_latency_ms;doublep95_latency_ms;doublep99_latency_ms;longbytes_received;longbytes_sent;};Resultrun(conststd::stringurl,intconcurrent_connections,inttotal_requests,intduration_seconds){std::coutRunning benchmark...std::endl;std::coutURL: urlstd::endl;std::coutConcurrent connections: concurrent_connectionsstd::endl;std::coutTotal requests: total_requestsstd::endl;std::coutDuration: duration_seconds secondsstd::endl;Result result{};std::vectorstd::threadworkers;std::vectorstd::vectorlonglatencies(concurrent_connections);std::atomiclongrequests_completed{0};std::atomiclongrequests_failed{0};std::atomiclongbytes_received{0};std::atomiclongbytes_sent{0};autoworker_func[](intworker_id){autostart_timestd::chrono::steady_clock::now();autoend_timestart_timestd::chrono::seconds(duration_seconds);while(std::chrono::steady_clock::now()end_timerequests_completedtotal_requests){autorequest_startstd::chrono::steady_clock::now();if(send_benchmark_request(url,bytes_sent,bytes_received)){requests_completed;autorequest_endstd::chrono::steady_clock::now();longlatencystd::chrono::duration_caststd::chrono::milliseconds(request_end-request_start).count();latencies[worker_id].push_back(latency);}else{requests_failed;}}};// 启动工作线程for(inti0;iconcurrent_connections;i){workers.emplace_back(worker_func,i);}// 等待所有线程完成for(autoworker:workers){worker.join();}// 计算统计信息result.total_requestsrequests_completedrequests_failed;result.successful_requestsrequests_completed;result.failed_requestsrequests_failed;result.bytes_receivedbytes_received;result.bytes_sentbytes_sent;// 计算RPSresult.requests_per_secondrequests_completed/static_castdouble(duration_seconds);// 收集所有延迟数据std::vectorlongall_latencies;for(constautoworker_latencies:latencies){all_latencies.insert(all_latencies.end(),worker_latencies.begin(),worker_latencies.end());}if(!all_latencies.empty()){// 计算平均延迟longlongtotal_latency0;for(longlatency:all_latencies){total_latencylatency;}result.average_latency_mstotal_latency/static_castdouble(all_latencies.size());// 计算百分位数std::sort(all_latencies.begin(),all_latencies.end());result.p50_latency_msall_latencies[all_latencies.size()*0.5];result.p95_latency_msall_latencies[all_latencies.size()*0.95];result.p99_latency_msall_latencies[all_latencies.size()*0.99];}returnresult;}voidprint_result(constResultresult){std::cout\n Benchmark Results std::endl;std::coutTotal requests: result.total_requestsstd::endl;std::coutSuccessful: result.successful_requests ((result.successful_requests*100.0/result.total_requests)%)std::endl;std::coutFailed: result.failed_requests ((result.failed_requests*100.0/result.total_requests)%)std::endl;std::coutRequests per second: result.requests_per_secondstd::endl;std::coutAverage latency: result.average_latency_ms msstd::endl;std::cout50th percentile: result.p50_latency_ms msstd::endl;std::cout95th percentile: result.p95_latency_ms msstd::endl;std::cout99th percentile: result.p99_latency_ms msstd::endl;std::coutBytes sent: format_bytes(result.bytes_sent)std::endl;std::coutBytes received: format_bytes(result.bytes_received)std::endl;std::coutThroughput: format_bytes(result.bytes_received/1024.0/1024.0)/sstd::endl;}private:boolsend_benchmark_request(conststd::stringurl,std::atomiclongbytes_sent,std::atomiclongbytes_received){// 解析URLURL parsed_url;if(!parsed_url.parse(url)){returnfalse;}// 创建socketintclient_fdsocket(AF_INET,SOCK_STREAM,0);if(client_fd0){returnfalse;}// 设置超时structtimevaltimeout;timeout.tv_sec5;timeout.tv_usec0;setsockopt(client_fd,SOL_SOCKET,SO_RCVTIMEO,timeout,sizeof(timeout));setsockopt(client_fd,SOL_SOCKET,SO_SNDTIMEO,timeout,sizeof(timeout));// 连接服务器structsockaddr_inserver_addr;server_addr.sin_familyAF_INET;server_addr.sin_porthtons(parsed_url.get_port());if(inet_pton(AF_INET,parsed_url.get_host().c_str(),server_addr.sin_addr)0){// 尝试域名解析structhostent*hostgethostbyname(parsed_url.get_host().c_str());if(hostnullptr){close(client_fd);returnfalse;}server_addr.sin_addr*((structin_addr*)host-h_addr);}if(connect(client_fd,(structsockaddr*)server_addr,sizeof(server_addr))0){close(client_fd);returnfalse;}// 构建请求std::stringstream request;requestGET parsed_url.get_path();if(!parsed_url.get_query_params().empty()){request?;boolfirsttrue;for(constautoparam:parsed_url.get_query_params()){if(!first)request;requestparam.firstparam.second;firstfalse;}}request HTTP/1.1\r\n;requestHost: parsed_url.get_host()\r\n;requestUser-Agent: BenchmarkClient/1.0\r\n;requestConnection: close\r\n;request\r\n;std::string request_strrequest.str();ssize_t sentwrite(client_fd,request_str.c_str(),request_str.length());if(sent0){close(client_fd);returnfalse;}bytes_sentsent;// 读取响应charbuffer[4096];ssize_t received0;while(true){ssize_t nread(client_fd,buffer,sizeof(buffer));if(n0){break;}receivedn;}bytes_receivedreceived;close(client_fd);returnreceived0;}std::stringformat_bytes(doublebytes){constchar*units[]{B,KB,MB,GB};intunit_index0;while(bytes1024.0unit_index3){bytes/1024.0;unit_index;}std::stringstream ss;ssstd::fixedstd::setprecision(2)bytes units[unit_index];returnss.str();}};// 使用示例voidrun_benchmarks(){Benchmark benchmark;// 测试静态文件服务std::cout\n Testing Static File Serving std::endl;autostatic_resultbenchmark.run(http://localhost:8080/index.html,10,10000,30);benchmark.print_result(static_result);// 测试API端点std::cout\n Testing API Endpoint std::endl;autoapi_resultbenchmark.run(http://localhost:8080/api/status,10,10000,30);benchmark.print_result(api_result);// 测试高并发std::cout\n Testing High Concurrency std::endl;autohigh_concurrency_resultbenchmark.run(http://localhost:8080/api/status,100,50000,60);benchmark.print_result(high_concurrency_result);}八、部署与监控8.1 生产环境部署#!/bin/bash# deploy.sh - 生产环境部署脚本set-e# 配置SERVER_NAMEsimple_http_serverINSTALL_DIR/opt/$SERVER_NAMECONFIG_DIR/etc/$SERVER_NAMELOG_DIR/var/log/$SERVER_NAMEUSER_NAMEhttpdGROUP_NAMEhttpdecho开始部署$SERVER_NAME...# 检查是否以root运行if[$EUID-ne0];thenecho请使用root权限运行此脚本exit1fi# 创建用户和组if!id$USER_NAME/dev/null;thenecho创建用户$USER_NAME...useradd-r -s /bin/false$USER_NAMEfi# 创建目录echo创建目录...mkdir-p$INSTALL_DIRmkdir-p$CONFIG_DIRmkdir-p$LOG_DIRmkdir-p$INSTALL_DIR/www# 设置权限echo设置权限...chown-R$USER_NAME:$GROUP_NAME$INSTALL_DIRchown-R$USER_NAME:$GROUP_NAME$CONFIG_DIRchown-R$USER_NAME:$GROUP_NAME$LOG_DIRchmod755$INSTALL_DIRchmod755$CONFIG_DIRchmod755$LOG_DIR# 复制文件echo复制文件...cphttpserver$INSTALL_DIR/cp-r www/*$INSTALL_DIR/www/cpserver.conf$CONFIG_DIR/cphttpserver.service /etc/systemd/system/# 创建配置文件if[!-f$CONFIG_DIR/server.conf];thencat$CONFIG_DIR/server.confEOF # 生产环境配置 server.port 80 server.address 0.0.0.0 server.root_dir $INSTALL_DIR/www server.thread_pool_size 8 server.max_connections 10000 # 日志配置 log.file $LOG_DIR/access.log log.level INFO log.access_log true # 安全配置 security.max_request_size 10485760 security.enable_cors true security.cors_origins * # 缓存配置 cache.enabled true cache.max_size 100000000 cache.default_ttl 3600 # 性能配置 performance.send_buffer_size 16384 performance.recv_buffer_size 16384 performance.keep_alive_timeout 15 performance.enable_gzip true EOFfi# 创建systemd服务文件cat/etc/systemd/system/httpserver.serviceEOF [Unit] DescriptionSimple HTTP Server Afternetwork.target [Service] Typesimple User$USER_NAMEGroup$GROUP_NAMEWorkingDirectory$INSTALL_DIRExecStart$INSTALL_DIR/httpserver -c$CONFIG_DIR/server.conf Restartalways RestartSec10 StandardOutputsyslog StandardErrorsyslog SyslogIdentifierhttpserver # 安全设置 NoNewPrivilegestrue PrivateTmptrue ProtectSystemstrict ProtectHometrue ReadWritePaths$LOG_DIR# 资源限制 LimitNOFILE65536 LimitNPROC4096 [Install] WantedBymulti-user.target EOF# 启用并启动服务echo配置systemd服务...systemctl daemon-reload systemctlenablehttpserver systemctl start httpserver# 检查服务状态ifsystemctl is-active --quiet httpserver;thenecho服务启动成功echo查看服务状态: systemctl status httpserverecho查看日志: journalctl -u httpserver -felseecho服务启动失败journalctl -u httpserver --no-pager -n20exit1fi# 配置防火墙ifcommand-v firewall-cmd/dev/null;thenecho配置防火墙...firewall-cmd --permanent --add-port80/tcp firewall-cmd --reloadfi# 配置日志轮转cat/etc/logrotate.d/httpserverEOF$LOG_DIR/*.log { daily missingok rotate 30 compress delaycompress notifempty create 640$USER_NAME$GROUP_NAMEsharedscripts postrotate systemctl reload httpserver /dev/null 21 || true endscript } EOFecho部署完成echo服务器运行在: http://$(hostname-I|awk{print$1}):808.2 监控配置#!/bin/bash# monitor.sh - 服务器监控脚本# 配置SERVER_NAMEhttpserverLOG_FILE/var/log/$SERVER_NAME/access.logSTATUS_FILE/tmp/$SERVER_NAME.statusALERT_EMAILadminexample.com# 监控函数check_server_status(){localstatus$(systemctl is-active $SERVER_NAME)if[$status!active];thensend_alertServer$SERVER_NAMEis$statussystemctl restart$SERVER_NAMEreturn1fireturn0}check_server_health(){# 检查HTTP响应localresponse$(curl-s -o /dev/null -w%{http_code}http://localhost/health)if[$response!200];thensend_alertHealth check failed with status$responsereturn1fireturn0}monitor_resources(){localcpu_usage$(top-bn1|grepCpu(s)|awk{print$2}|cut-d%-f1)localmem_usage$(free|grepMem|awk{print$3/$2* 100.0})localdisk_usage$(df/|tail-1|awk{print$5}|cut-d%-f1)localconnections$(netstat-an|grep:80|grepESTABLISHED|wc-l)echoCPU:${cpu_usage}% | Memory:${mem_usage}% | Disk:${disk_usage}% | Connections:$connections$STATUS_FILE# 检查资源使用率if(($(echo $cpu_usage90|bc-l)));thensend_alertHigh CPU usage:${cpu_usage}%fiif(($(echo $mem_usage90|bc-l)));thensend_alertHigh memory usage:${mem_usage}%fiif[$disk_usage-gt90];thensend_alertHigh disk usage:${disk_usage}%fi}analyze_logs(){# 分析错误日志localerrors$(tail-1000 $LOG_FILE|grep-ierror\|fail\|exception|wc-l)localrate$(tail-1000 $LOG_FILE|grepHTTP/1.1|awk{print$9}|grep-E4[0-9]{2}|5[0-9]{2}|wc-l)if[$errors-gt10];thensend_alertHigh error rate in logs:$errorserrors in last 1000 entriesfiif[$rate-gt50];thensend_alertHigh HTTP error rate:$rateerrors in last 1000 requestsfi}monitor_performance(){# 监控请求处理时间localavg_time$(tail-1000 $LOG_FILE|grepHTTP/1.1\200|awk{print$(NF-1)}|seds/ms//|awk{sum$1} END {print sum/NR})if(($(echo $avg_time1000|bc-l)));thensend_alertHigh average response time:${avg_time}msfi}send_alert(){localmessage$1echo[$(date)] ALERT:$message/var/log/$SERVER_NAME/monitor.log# 发送邮件需要配置邮件服务器# echo $message | mail -s Server Alert: $SERVER_NAME $ALERT_EMAIL# 发送到Slack示例# curl -X POST -H Content-type: application/json \# --data {\text\:\$message\} \# https://hooks.slack.com/services/XXX/YYY/ZZZ}# 生成监控报告generate_report(){localreport_file/tmp/$SERVER_NAME-report-$(date%Y%m%d).txtcat$report_fileEOF Server Monitoring Report Date:$(date)Server:$SERVER_NAME1. System Status:$(systemctl status $SERVER_NAME --no-pager)2. Resource Usage:$(cat$STATUS_FILE)3. Recent Errors ($(date-d1 hour ago%H:%M:%S)-$(date%H:%M:%S)):$(tail-1000 $LOG_FILE|grep-ierror\|fail\|exception|tail-10)4. Top Endpoints:$(tail-1000 $LOG_FILE|grepHTTP/1.1\200|awk{print$7}|sort|uniq-c|sort-rn|head-10)5. Response Time Statistics:$(tail-1000 $LOG_FILE|grepHTTP/1.1\200|awk{print$(NF-1)}|seds/ms//|\awkBEGIN {min999999; max0} {sum$1; count; if($1min) min$1; if($1max) max$1} \ END {print Count: count; print Min: min ms; print Max: max ms; \ print Avg: (sum/count) ms; print Sum: sum ms})6. Active Connections:$(netstat-an|grep:80|grepESTABLISHED|wc-l)established connections 7. Disk Usage:$(df-h /)8. Memory Usage:$(free-h)EOFechoReport generated:$report_file}# 主循环whiletrue;doecho[$(date)] Starting monitoring cycle...check_server_status check_server_health monitor_resources analyze_logs monitor_performance# 每小时生成一次报告if[$(date%M)00];thengenerate_reportfisleep60# 每分钟检查一次done8.3 Docker容器化# Dockerfile FROM ubuntu:22.04 # 安装依赖 RUN apt-get update apt-get install -y \ g \ make \ cmake \ libjsoncpp-dev \ libssl-dev \ rm -rf /var/lib/apt/lists/* # 创建工作目录 WORKDIR /app # 复制源代码 COPY . . # 编译 RUN make clean make # 创建运行时用户 RUN groupadd -r httpd useradd -r -g httpd httpd # 创建必要的目录 RUN mkdir -p /var/log/httpserver \ chown -R httpd:httpd /var/log/httpserver # 复制配置文件 COPY server.conf /etc/httpserver/server.conf # 暴露端口 EXPOSE 80 443 # 设置健康检查 HEALTHCHECK --interval30s --timeout3s --start-period5s --retries3 \ CMD curl -f http://localhost:80/health || exit 1 # 切换用户 USER httpd # 启动命令 CMD [./httpserver, -c, /etc/httpserver/server.conf]# docker-compose.ymlversion:3.8services:httpserver:build:.container_name:simple_http_serverrestart:unless-stoppedports:-80:80-443:443volumes:-./www:/app/www-./logs:/var/log/httpserver-./config:/etc/httpserverenvironment:-SERVER_PORT80-SERVER_ROOT/app/www-LOG_LEVELINFOnetworks:-webnetdeploy:resources:limits:cpus:1memory:512Mreservations:cpus:0.5memory:256Mhealthcheck:test:[CMD,curl,-f,http://localhost:80/health]interval:30stimeout:10sretries:3start_period:40snginx:image:nginx:alpinecontainer_name:nginx_proxyrestart:unless-stoppedports:-8080:80volumes:-./nginx.conf:/etc/nginx/nginx.conf-./ssl:/etc/nginx/ssldepends_on:-httpservernetworks:-webnetmonitor:image:prom/prometheus:latestcontainer_name:prometheusrestart:unless-stoppedports:-9090:9090volumes:-./prometheus.yml:/etc/prometheus/prometheus.yml-prometheus_data:/prometheuscommand:---config.file/etc/prometheus/prometheus.yml---storage.tsdb.path/prometheus---web.console.libraries/etc/prometheus/console_libraries---web.console.templates/etc/prometheus/consoles---storage.tsdb.retention.time200h---web.enable-lifecyclenetworks:-webnetgrafana:image:grafana/grafana:latestcontainer_name:grafanarestart:unless-stoppedports:-3000:3000environment:-GF_SECURITY_ADMIN_PASSWORDadminvolumes:-grafana_data:/var/lib/grafana-./grafana/provisioning:/etc/grafana/provisioningnetworks:-webnetdepends_on:-monitornetworks:webnet:driver:bridgevolumes:prometheus_data:driver:localgrafana_data:driver:local# prometheus.ymlglobal:scrape_interval:15sevaluation_interval:15sscrape_configs:-job_name:httpserverstatic_configs:-targets:[httpserver:80]metrics_path:/metricsscrape_interval:10s-job_name:node_exporterstatic_configs:-targets:[node_exporter:9100]alerting:alertmanagers:-static_configs:-targets:# - alertmanager:9093rule_files:# - first_rules.yml# - second_rules.yml九、总结与展望9.1 本文总结本文详细介绍了从零开始构建一个完整的HTTP服务器的全过程涵盖了以下主要内容服务器设计流程从TCP服务器基础到Reactor模式的事件驱动架构HTTP协议详解包括URL解析、请求响应格式、状态码、头部字段等代码实现完整的HTTP服务器实现支持静态文件服务和API端点GET/POST方法详细的数据获取和处理机制包括文件上传安全考虑XSS防护、SQL注入防护、CSRF防护等性能优化缓存、连接池、内存池、零拷贝技术等测试验证单元测试、集成测试、性能基准测试部署监控生产环境部署、监控脚本、Docker容器化通过本文的学习读者可以深入理解HTTP协议的工作原理掌握高性能HTTP服务器的设计和实现学习网络编程的最佳实践和安全考虑了解服务器性能优化和监控的方法获得一个可扩展的HTTP服务器基础框架9.2 扩展方向基于本文实现的HTTP服务器还可以进一步扩展以下功能9.2.1 支持HTTP/2和HTTP/3// HTTP/2支持的基本框架classHttp2Handler{public:boolhandle_http2_connection(intclient_fd){// 检查客户端是否支持HTTP/2// 发送HTTP/2设置帧// 实现多路复用// 实现头部压缩returntrue;}};9.2.2 WebSocket支持classWebSocketHandler{public:boolhandle_upgrade(constHttpRequestrequest,HttpResponseresponse){// 检查Upgrade头if(request.get_header(Upgrade)!websocket){returnfalse;}// 生成Sec-WebSocket-Acceptstd::string keyrequest.get_header(Sec-WebSocket-Key);std::string acceptgenerate_websocket_accept(key);// 发送升级响应response.set_status(101);response.set_header(Upgrade,websocket);response.set_header(Connection,Upgrade);response.set_header(Sec-WebSocket-Accept,accept);returntrue;}voidhandle_websocket_frame(intclient_fd){// 解析WebSocket帧// 处理文本/二进制消息// 实现ping/pong// 处理连接关闭}};9.2.3 负载均衡和集群classLoadBalancer{private:std::vectorstd::stringbackend_servers;std::atomicsize_tcurrent_index{0};public:enumBalancingStrategy{ROUND_ROBIN,LEAST_CONNECTIONS,IP_HASH,WEIGHTED};std::stringselect_backend(constHttpRequestrequest,BalancingStrategy strategy){switch(strategy){caseROUND_ROBIN:returnround_robin();caseLEAST_CONNECTIONS:returnleast_connections();caseIP_HASH:returnip_hash(request);caseWEIGHTED:returnweighted();default:returnround_robin();}}private:std::stringround_robin(){size_t indexcurrent_index%backend_servers.size();returnbackend_servers[index];}};9.2.4 数据库集成classDatabaseManager{private:sqlite3*db;public:boolinit(conststd::stringdb_file){if(sqlite3_open(db_file.c_str(),db)!SQLITE_OK){returnfalse;}// 创建表constchar*create_table_sqlCREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT,username TEXT UNIQUE NOT NULL,email TEXT UNIQUE NOT NULL,password_hash TEXT NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);;returnexecute_sql(create_table_sql);}Json::Valuequery_users(){Json::Valueresult(Json::arrayValue);sqlite3_stmt*stmt;constchar*sqlSELECT id, username, email, created_at FROM users;if(sqlite3_prepare_v2(db,sql,-1,stmt,nullptr)SQLITE_OK){while(sqlite3_step(stmt)SQLITE_ROW){Json::Value user;user[id]sqlite3_column_int(stmt,0);user[username]reinterpret_castconstchar*(sqlite3_column_text(stmt,1));user[email]reinterpret_castconstchar*(sqlite3_column_text(stmt,2));user[created_at]reinterpret_castconstchar*(sqlite3_column_text(stmt,3));result.append(user);}sqlite3_finalize(stmt);}returnresult;}};9.2.5 模板引擎支持classTemplateEngine{public:std::stringrender(conststd::stringtemplate_file,conststd::mapstd::string,std::stringcontext){std::ifstreamfile(template_file);if(!file){returnTemplate not found;}std::stringcontent((std::istreambuf_iteratorchar(file)),std::istreambuf_iteratorchar());// 简单模板变量替换for(constautovar:context){std::string placeholder{{var.first}};size_t pos0;while((poscontent.find(placeholder,pos))!std::string::npos){content.replace(pos,placeholder.length(),var.second);posvar.second.length();}}// 处理循环和条件简化版process_loops(content,context);process_conditionals(content,context);returncontent;}private:voidprocess_loops(std::stringcontent,conststd::mapstd::string,std::stringcontext){// 实现简单的循环逻辑// 例如: {% for item in items %}...{% endfor %}}voidprocess_conditionals(std::stringcontent,conststd::mapstd::string,std::stringcontext){// 实现简单的条件逻辑// 例如: {% if condition %}...{% endif %}}};9.3 学习资源推荐书籍推荐《HTTP权威指南》《UNIX网络编程》《Linux多线程服务端编程》《深入理解计算机系统》开源项目学习Nginx高性能HTTP和反向代理服务器Apache HTTP Server最流行的Web服务器Node.jsJavaScript运行时事件驱动架构Redis高性能键值存储网络编程范例在线资源MDN Web DocsHTTP协议文档RFC文档HTTP/1.1 RFC 2616HTTP/2 RFC 7540GitHub开源HTTP服务器项目工具推荐Wireshark网络协议分析curlHTTP客户端工具abApache基准测试工具wrk现代HTTP基准测试工具9.4 结语构建一个完整的HTTP服务器是一个复杂但非常有教育意义的项目。通过这个项目我们可以深入理解网络编程、协议设计、性能优化和安全防护等多个方面的知识。本文提供的代码和思路可以作为学习和实践的基础读者可以根据自己的需求进行扩展和优化。记住编写服务器软件需要特别注意安全性、稳定性和性能。在实际生产环境中部署时一定要进行充分的测试和监控。希望本文能够帮助读者深入理解HTTP服务器的工作原理并为开发高性能网络应用打下坚实的基础。网络编程的世界充满挑战但也充满乐趣祝你在学习过程中有所收获本文总字数约25000字代码行数约1500行*创作时间2025*作者福尔摩斯张版权声明本文代码遵循MIT开源协议可自由使用和修改但需保留版权声明
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

沈阳网站制作联系方式hishop官网

Qwen3-Embedding-4B-GGUF:重构企业语义检索成本效益比的技术革命 【免费下载链接】Qwen3-Embedding-4B-GGUF 项目地址: https://ai.gitcode.com/hf_mirrors/Qwen/Qwen3-Embedding-4B-GGUF 语义检索技术正面临成本与性能的双重挑战,传统商业API服…

张小明 2026/1/1 10:26:34 网站建设

网站登录界面模板如何做自助网站

YOLOv10-E-Lite发布!专为低功耗GPU设计 在智能制造产线高速运转的今天,一个看似简单的视觉质检任务背后,往往隐藏着巨大的算力挑战:既要精准识别微米级缺陷,又要保证每秒数十帧的实时响应。而传统的高性能目标检测模型…

张小明 2026/1/1 15:17:03 网站建设

网站建设引擎网站推广优化业务

目录 一、引言 1.1 研究背景与意义 1.2 研究目的 1.3 国内外研究现状 二、大模型预测呼吸衰竭的原理与方法 2.1 常用大模型介绍 2.2 数据收集与预处理 2.3 模型训练与验证 三、术前风险预测与准备方案 3.1 术前风险因素分析 3.2 大模型预测术前风险的方法与结果 3.3…

张小明 2026/1/2 0:09:10 网站建设

汕头教育学会网站建设枝江网站建设

还在为玩彩虹岛韩服时遇到的中文乱码而烦恼吗?你是否曾经纳闷,明明启动了Locale Remulator,为什么游戏里的文字还是显示不正常?今天,我们就来深入探讨这个技术难题的解决方法! 【免费下载链接】Locale_Remu…

张小明 2026/1/8 20:56:28 网站建设

互助盘网站建设河南省水利建设厅网站

考场作弊行为识别系统:公平公正的技术保障 在高考、研究生入学考试等重大教育场景中,任何一次监考疏漏都可能动摇公众对选拔制度的信任。尽管监考老师尽职尽责,但面对数十名考生同时作答的复杂环境,人的注意力终有盲区——低头时间…

张小明 2025/12/30 7:55:35 网站建设

狗和人做网站如何做类似千图网的网站

喜马拉雅音频下载终极指南:从零开始掌握批量下载技巧 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 想要建立个人专属…

张小明 2026/1/6 4:06:47 网站建设