1. 为什么我们需要自己实现Web计算器
在当今互联网时代,Web服务已经成为各种应用的基础设施。你可能会有疑问:市面上已经有那么多成熟的Web框架和计算器应用,为什么还要自己动手实现一个?这个问题很好,让我从几个方面来解释。
首先,从学习角度来看,自己实现一个完整的Web服务能让你深入理解HTTP协议的工作机制。很多开发者只是会使用框架,但对底层原理一知半解。当你亲手处理HTTP请求解析、路由分发、业务逻辑处理和响应构建这一完整链路时,对Web开发的理解会完全不同。
其次,从技术栈选择来看,C++作为高性能系统编程语言,在处理计算密集型任务时有着天然优势。虽然Python、Node.js等语言在Web开发中更常见,但在需要极致性能的场景下,C++仍然是不可替代的选择。我们的计算器虽然简单,但可以作为一个很好的起点,未来可以扩展为高性能科学计算服务。
再者,JSON作为轻量级数据交换格式,已经成为现代Web API的事实标准。通过这个项目,你将掌握如何在C++中处理JSON数据,这在物联网、游戏服务器等C++应用场景中是非常实用的技能。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 项目架构设计
2.1 整体架构
我们的Web计算器服务器将采用经典的客户端-服务器架构。客户端(可以是浏览器、Postman或curl等工具)发送HTTP请求,服务器接收请求、处理计算逻辑,然后返回JSON格式的响应。
整个系统由以下几个核心组件构成:
- 网络通信层:负责监听端口、接收请求和发送响应
- 协议解析层:解析HTTP请求,提取方法和参数
- 业务逻辑层:执行实际的计算操作
- 数据格式层:处理JSON的序列化和反序列化
2.2 技术选型
对于网络通信,我们将使用Linux下的socket API。虽然现代C++有Boost.Asio等高级网络库,但直接使用socket API能让我们更深入理解网络编程的本质。
JSON处理方面,我们选择nlohmann/json这个流行的C++ JSON库。它提供了直观的API,完全符合现代C++的编程风格。
3. 开发环境准备
3.1 基础工具安装
在开始编码前,我们需要确保开发环境已经配置好必要的工具链:
bash复制sudo apt update
sudo apt install g++ cmake make git -y
3.2 JSON库安装
我们将使用nlohmann/json这个头文件库,安装非常简单:
bash复制sudo apt install nlohmann-json3-dev
或者你也可以直接从GitHub获取单头文件版本:
bash复制wget https://github.com/nlohmann/json/releases/download/v3.11.2/json.hpp
3.3 项目目录结构
建议采用以下目录结构组织项目:
code复制web-calculator/
├── include/ # 头文件
├── src/ # 源文件
├── test/ # 测试代码
├── CMakeLists.txt # 构建配置
└── README.md # 项目说明
4. 核心代码实现
4.1 创建HTTP服务器
我们先实现一个基本的HTTP服务器框架:
cpp复制#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <string>
class HttpServer {
public:
HttpServer(int port) : port_(port) {}
void start() {
int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) {
std::cerr << "Failed to create socket" << std::endl;
return;
}
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port_);
if (bind(server_fd, (sockaddr*)&address, sizeof(address)) < 0) {
std::cerr << "Failed to bind socket" << std::endl;
return;
}
if (listen(server_fd, 10) < 0) {
std::cerr << "Failed to listen" << std::endl;
return;
}
std::cout << "Server started on port " << port_ << std::endl;
while (true) {
sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int client_fd = accept(server_fd, (sockaddr*)&client_addr, &client_len);
if (client_fd < 0) {
std::cerr << "Failed to accept connection" << std::endl;
continue;
}
handleRequest(client_fd);
close(client_fd);
}
}
private:
int port_;
void handleRequest(int client_fd) {
char buffer[1024] = {0};
read(client_fd, buffer, sizeof(buffer));
std::string response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\nHello, World!";
write(client_fd, response.c_str(), response.size());
}
};
4.2 实现JSON请求处理
接下来我们扩展handleRequest方法,使其能够处理JSON格式的请求:
cpp复制#include "json.hpp"
using json = nlohmann::json;
void handleRequest(int client_fd) {
char buffer[4096] = {0};
read(client_fd, buffer, sizeof(buffer));
std::string request(buffer);
size_t body_pos = request.find("\r\n\r\n");
if (body_pos == std::string::npos) {
sendErrorResponse(client_fd, "Invalid request format");
return;
}
std::string body = request.substr(body_pos + 4);
try {
json request_json = json::parse(body);
json response_json = processCalculation(request_json);
std::string response = "HTTP/1.1 200 OK\r\n";
response += "Content-Type: applicati
