C++實現(xiàn)HTTP服務的示例代碼
一、C++Web服務器(核心代碼WebServer.cpp)
要實現(xiàn)一個簡單的C++Web服務器,支持GET和POST請求,同時能夠提供靜態(tài)文件(如JavaScript、CSS和圖片文件)。
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <unordered_map>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/stat.h>
using namespace std;
#define PORT 8080 // 端口號
#define BUFFER_SIZE 4096 // 緩沖區(qū)大小
//根據(jù)文件拓展名返回適當?shù)腃ontent-Type
std::string getContentType(const std::string &path){
if(path.ends_with(".html")) return "text/html";
if(path.ends_with(".css")) return "text/css";
if(path.ends_with(".js")) return "application/javascript";
if(path.ends_with(".png")) return "image/png";
if(path.ends_with(".jpg")) return "image/jpeg";
if(path.ends_with(".jpeg")) return "image/jpeg";
if(path.ends_with(".gif")) return "image/gif";
return "text/plain";
}
//讀取靜態(tài)文件
std::string readFile(const std::string &path){
//創(chuàng)建一個輸入文件流對象,以二進制模式打開指定路徑的文件
std::ifstream file(path,std::ios::binary);
//檢查文件是否成功打開
if(!file.is_open()){
perror("file open failed");
//如果打開失敗返回空字符串
return "";
}
//創(chuàng)建一個輸出字符串流對象,用于將文件內(nèi)容讀取到字符串
std::ostringstream ss;
//使用輸出字符串流對象的rdbuf()將文件內(nèi)容讀取到字符串中
//這實際上是將文件流中的所有字節(jié)復制到字符串流的緩沖區(qū)中
ss<<file.rdbuf();
//將字符串流的內(nèi)容轉(zhuǎn)換為std::string并返回
return ss.str();
}
//判斷文件是否存在
bool fileExists(const std::string &path){
struct stat buffer;
return stat(path.c_str(), &buffer)==0;
}
int main() {
// 創(chuàng)建套接字
int server_fd, new_socket;
// 地址結(jié)構(gòu)體
struct sockaddr_in address;
int opt=1; // 設(shè)置套接字選項
int addlen = sizeof(address);// 地址結(jié)構(gòu)體長度
char buffer[BUFFER_SIZE] = {0}; // 緩沖區(qū)
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0))==0){
perror("socket failed");
exit(EXIT_FAILURE);
}
//設(shè)置端口復用
//如果你不是用SO_REUSEADDR,服務器程序關(guān)閉后,可能會出現(xiàn)“Address already in use” 錯誤
//尤其是當你嘗試在同一個端口上重新啟動服務器時,這是因為TCP連接可能會保持TIME_WAIT的狀態(tài)一段時間
//而SO_REUSEADDR允許套接字在這種狀態(tài)下重新綁定到另一個端口
if(setsoocketopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))){
perror("setsoocketopt failed");
exit(EXIT_FAILURE);
}
//配置服務器地址
addrss.sin_family = AF_INET;
addrss.sin_addr.s_addr = INADDR_ANY;
addrss.sin_port = htons(PORT);
//綁定套接字
if(bind(server_fd, (struct sockaddr *)&address, addlen)<0){
perror("bind failed");
exit(EXIT_FAILURE);
}
//監(jiān)聽請求
if(listen(server_fd, 3)<0){
perror("listen failed");
exit(EXIT_FAILURE);
}
cout<<"WebServer is running on port"<<PORT<<"....\n";
while(true)
{
//接受客戶端連接
if((new_socket=accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addlen))<0){
perror("accept failed");
exit(EXIT_FAILURE);
}
//讀取客戶端請求
read(new_socket, buffer, BUFFER_SIZE);
cout<<"Request received :\n"<<buffer<<endl;
//解析Http請求
//這段代碼是解析Http請求中提取 請求方法、路徑和Http版本。如下:
//第一次提取method,得到:GET
//第二次提取path,得到:/index.html
//第三次提取version,得到:HTTP/1.1
std::istringstream request(buffer);
std::string method , path , version;
request>>method>>path>>version;
//默認首頁
if(path=="/")
{
path="/index.html";
}
//構(gòu)建文件路徑
std::string filePath ="."+path;
//處理GET請求
if(method=="GET"){
if(fileExists(filePath)){//文件存在
std::string content = readFile(filePath);//讀取文件內(nèi)容
std::string contentType = getContentType(filePath);//獲取文件類型
std::ostringstream response; // 構(gòu)建響應
response<<"HTTP/1.1 200 OK\r\n"
<<"Content-Type:"<<contentType<<"\r\n"
<<"Content-Length:"<<content.length()<<"\r\n"
<<"\r\n"
<<content;//響應頭和響應體
response<<content;
//發(fā)送響應
send(new_socket, response.str().c_str(), response.str().length(), 0);
}else{
//404 NOT FOUND
std::string notFound="HTTP/1.1 404 Not Found\r\n\r\n404 Not Found";
send(new_socket, notFound.c_str(), notFound.length(), 0);
}
}
else if(method=="POST"){//處理POST請求
//簡單的響應客戶端的POST請求(可以根據(jù)需要解析POST請求)
std::string response="HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nPOST request";
send(new_socket, response.c_str(), response.length(), 0);
}else{
//405 METHOD NOT ALLOWED
std::string notAllowed="HTTP/1.1 405 Method Not Allowed\r\n\r\n405 Method Not Allowed";
send(new_socket, notAllowed.c_str(), notAllowed.length(), 0);
}
//關(guān)閉連接
close(new_socket);
}
//釋放資源,關(guān)閉服務器套接字
close(server_fd);
return 0;
}
二、靜態(tài)文件結(jié)構(gòu)
- 確保你的HTML、CSS、JS和圖片文件都存放在與可執(zhí)行程序相同的目錄下或適當?shù)淖幽夸浿?,例如?/li>
./index.html ./style.css ./script.js ./images/example.jjpg

假設(shè)HTL文件是這樣的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>這是一個簡單的WebServer</title>
<style>
body{
font-family: Arial,sans-serif;
background-color: #f4f4f9;
color: #333;
margin: 0;
padding: 0;
}
header{
background-color: #4CAF50;
color: white;
padding: 10px 0;
}
h1{
margin: 0;
}
p{
font-size: 1.2em;
margin: 20px auto;
width: 80%;
}
footer{
position: fixed;
bottom: 0;
width: 100%;
background-color: #4CAF50;
color: white;
padding: 10px 0;
}
</style>
</head>
<body>
<header>
<h1>這是一個簡單的WebServer</h1>
</header>
<main>
<p>這是一個簡單的WebServer,你可以在這里放置一些內(nèi)容。</p>
<br/>
<img src="23.png" alt="C++測試">
</main>
<footer>
<p>
©2025 My WebServer By HuJiaHang
</p>
</footer>
</body>
</html>
三、編譯和運行
- 編譯
g++ -std=c++20 WebServer.cpp -o WebServer //使用C++20標準,是因為std::string::ends_with()是C++20引入的功能
- 運行:執(zhí)行編譯好的WebServer程序
./WebServer
四、訪問測試
使用瀏覽器訪問http://localhost:8080,可以獲取靜態(tài)HTML頁面、CSS樣式、JavaScript腳本和圖片
注意:如果使用的是云服務器,就必須要在安全組中放開端口
以下是我的測試


到此這篇關(guān)于C++實現(xiàn)HTTP服務的示例代碼的文章就介紹到這了,更多相關(guān)C++ HTTP服務內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言實現(xiàn)古代時辰計時與現(xiàn)代時間換算
這篇文章主要為大家詳細介紹了如何利用C語言實現(xiàn)古代時辰計時與現(xiàn)代時間換算,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2023-03-03
C++通過循環(huán)實現(xiàn)猜數(shù)字小游戲
這篇文章主要為大家詳細介紹了C++通過循環(huán)實現(xiàn)猜數(shù)字小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-09-09
C++中的取余函數(shù)remainder與fmod詳解
這篇文章主要為大家詳細介紹了C++中的取余函數(shù)remainder、fmod的具體使用以及自編的remainder及fmod,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習學習2023-05-05

