1. 前置知识
Web服务器的核心任务是处理客户端发来的HTTP请求并返回HTTP响应。实现这一功能的第一步是理解网络套接字。套接字是一种允许程序与网络通信的机制。在Linux中,创建和使用套接字的一般流程如下:
- 创建套接字(socket):套接字函数
socket()
用于创建一个网络端点。 - 绑定地址(bind):
bind()
函数将套接字绑定到一个IP地址和端口号。 - 监听连接(listen):
listen()
函数使套接字进入监听状态,等待客户端连接。 - 接受连接(accept):当有客户端请求时,
accept()
函数会接受该连接并返回一个新的套接字来处理客户端通信。 - 处理请求:通过读取客户端请求数据,解析HTTP请求并生成响应。
- 发送响应:将HTTP响应发送回客户端。
2. 基本的C++代码结构
以下是用C++编写一个简单Web服务器的基本框架。
#include <iostream>
#include <unistd.h>
#include <arpa/inet.h>
#include <cstring>
#define PORT 8080
void handle_client(int client_socket) {
char buffer[1024] = {0};
read(client_socket, buffer, 1024);
std::cout << "Request:\n" << buffer << std::endl;
const char* response =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n\r\n"
"<html><body><h1>Hello, World!</h1></body></html>";
write(client_socket, response, strlen(response));
close(client_socket);
}
int main() {
int server_fd, client_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
// 1. 创建套接字
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket failed");
exit(EXIT_FAILURE);
}
// 2. 绑定地址和端口
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
perror("Bind failed");
close(server_fd);
exit(EXIT_FAILURE);
}
// 3. 监听连接
if (listen(server_fd, 3) < 0) {
perror("Listen failed");
close(server_fd);
exit(EXIT_FAILURE);
}
std::cout << "Server is listening on port " << PORT << std::endl;
// 4. 接受客户端连接并处理请求
while (true) {
if ((client_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen)) < 0) {
perror("Accept failed");
close(server_fd);
exit(EXIT_FAILURE);
}
// 处理客户端请求
handle_client(client_socket);
}
close(server_fd);
return 0;
}
3. 代码分析
- 创建套接字:通过
socket()
函数创建一个套接字,参数AF_INET
指定使用IPv4,SOCK_STREAM
指定使用TCP协议。 - 绑定端口:使用
bind()
函数将服务器的套接字绑定到指定的IP地址和端口。在这里,INADDR_ANY
表示服务器将监听所有网络接口。 - 监听连接:通过
listen()
函数使套接字进入监听模式,能够接受来自客户端的连接请求。 - 接受连接并处理请求:在
while (true)
循环中,服务器通过accept()
函数接受客户端连接,读取HTTP请求,并返回简单的HTTP响应。
4. 编译和运行
编译代码:
g++ -o web_server web_server.cpp
运行服务器:
./web_server
服务器启动后,将监听8080
端口。你可以通过浏览器访问http://localhost:8080
,或使用curl
命令进行测试:
curl http://localhost:8080