C++ Asio含完成处理程序的循环代码位置咨询
嘿,针对你在Asio中添加连接重试循环和请求创建循环的问题,我结合Asio的异步模型给你梳理下清晰的放置思路,直接上干货~
核心原则:区分两个循环的职责
首先得明确两个循环的定位:
- 连接重试循环:属于Client类的连接管理职责,解决TCP连接建立失败的重试问题
- 请求创建循环:属于业务逻辑层职责,负责批量生成HTTP请求;如果是请求发送/响应失败的重试(非连接层面),则属于Client的请求处理职责
1. 连接重试循环:放在Client类内部
连接重试是Client本身要处理的底层逻辑,适合封装在Client类里,用Asio的异步延迟+递归调用实现(避免阻塞io_context)。这里给你一个具体的实现示例:
#include <asio.hpp> #include <queue> #include <functional> #include <iostream> // 假设你已经定义了HTTPRequest、HTTPResponse类 class HTTPRequest {}; class HTTPResponse {}; class Client { public: Client(asio::io_context& io_context) : io_context_(io_context), socket_(io_context) {} // 设置连接结果回调 void set_connect_callback(std::function<void(const asio::error_code&)> callback) { connect_callback_ = std::move(callback); } // 带重试的连接方法 void connect_with_retry(const std::string& host, uint16_t port, int max_retries, std::chrono::seconds retry_delay) { do_connect(host, port, max_retries, retry_delay); } // 添加请求到队列 void add_request(const HTTPRequest& request) { request_queue_.push(request); } private: void do_connect(const std::string& host, uint16_t port, int remaining_retries, std::chrono::seconds retry_delay) { asio::ip::tcp::resolver resolver(io_context_); auto endpoints = resolver.resolve(host, std::to_string(port)); asio::async_connect(socket_, endpoints, [this, host, port, remaining_retries, retry_delay](const asio::error_code& ec, const asio::ip::tcp::endpoint&) { if (!ec) { std::cout << "连接成功!" << std::endl; // 连接成功后,开始处理请求队列 send_next_request(); if (connect_callback_) { connect_callback_(ec); } } else { if (remaining_retries > 0) { std::cout << "连接失败:" << ec.message() << ",剩余重试次数:" << remaining_retries << "," << retry_delay.count() << "秒后重试..." << std::endl; // 异步延迟后重试 asio::steady_timer timer(io_context_, retry_delay); timer.async_wait( [this, host, port, remaining_retries, retry_delay](const asio::error_code& timer_ec) { if (!timer_ec) { do_connect(host, port, remaining_retries - 1, retry_delay); } } ); } else { std::cout << "连接失败,已达最大重试次数" << std::endl; if (connect_callback_) { connect_callback_(ec); } } } } ); } void send_next_request() { if (!request_queue_.empty()) { HTTPRequest request = request_queue_.front(); request_queue_.pop(); // 这里调用你的请求发送逻辑(比如send_request_with_retry) // send_request_with_retry(request, 3, std::chrono::seconds(1)); } } asio::io_context& io_context_; asio::ip::tcp::socket socket_; std::function<void(const asio::error_code&)> connect_callback_; std::queue<HTTPRequest> request_queue_; };
2. 请求创建循环:分两种场景处理
场景1:批量创建请求(业务逻辑层)
如果是要生成多个不同的HTTP请求(比如从文件读取、循环生成参数化请求),这个循环应该放在Client类外部的业务代码里(比如main函数、业务模块),把创建好的请求加入Client的队列即可:
int main() { asio::io_context io_context; Client client(io_context); // 设置连接回调 client.set_connect_callback([](const asio::error_code& ec) { if (!ec) { std::cout << "开始处理请求队列..." << std::endl; } else { std::cerr << "最终连接失败:" << ec.message() << std::endl; } }); // 请求创建循环:批量生成10个参数化请求 for (int i = 0; i < 10; ++i) { HTTPRequest request; // 假设你的HTTPRequest有这些设置方法 // request.set_method("GET"); // request.set_path("/api/item/" + std::to_string(i)); // request.set_host("your-server.com"); client.add_request(request); } // 启动带重试的连接 client.connect_with_retry("your-server.com", 80, 3, std::chrono::seconds(2)); // 运行Asio的io_context io_context.run(); return 0; }
场景2:请求自身的重试(Client类内部)
如果是请求发送/响应失败(比如5xx状态码、网络中断)需要重试,这个重试逻辑应该放在Client的请求处理方法里,同样用异步延迟实现:
// 在Client类中添加请求重试逻辑 void Client::send_request_with_retry(const HTTPRequest& request, int max_retries, std::chrono::seconds retry_delay) { do_send_request(request, max_retries, retry_delay); } void Client::do_send_request(const HTTPRequest& request, int remaining_retries, std::chrono::seconds retry_delay) { // 序列化请求(假设你的HTTPRequest有serialize方法) std::string request_data = request.serialize(); asio::async_write(socket_, asio::buffer(request_data), [this, request, remaining_retries, retry_delay](const asio::error_code& ec, std::size_t) { if (!ec) { // 读取响应(假设用buffer暂存) asio::async_read_until(socket_, response_buffer_, "\r\n\r\n", [this, request, remaining_retries, retry_delay](const asio::error_code& read_ec, std::size_t) { if (!read_ec) { HTTPResponse response; response.parse(response_buffer_); // 判断是否需要重试(比如5xx状态码) if (response.get_status_code() >= 500 && remaining_retries > 0) { std::cout << "请求返回错误码" << response.get_status_code() << ",剩余重试次数:" << remaining_retries << ",延迟重试..." << std::endl; asio::steady_timer timer(io_context_, retry_delay); timer.async_wait( [this, request, remaining_retries, retry_delay](const asio::error_code& timer_ec) { if (!timer_ec) { do_send_request(request, remaining_retries - 1, retry_delay); } } ); } else { // 调用请求回调返回结果 if (request_callback_) { request_callback_(request, response, read_ec); } } } else { handle_request_failure(request, read_ec, remaining_retries, retry_delay); } } ); } else { handle_request_failure(request, ec, remaining_retries, retry_delay); } } ); } void Client::handle_request_failure(const HTTPRequest& request, const asio::error_code& ec, int remaining_retries, std::chrono::seconds retry_delay) { if (remaining_retries > 0) { std::cout << "请求失败:" << ec.message() << ",剩余重试次数:" << remaining_retries << ",延迟重试..." << std::endl; asio::steady_timer timer(io_context_, retry_delay); timer.async_wait( [this, request, remaining_retries, retry_delay](const asio::error_code& timer_ec) { if (!timer_ec) { do_send_request(request, remaining_retries - 1, retry_delay); } } ); } else { if (request_callback_) { request_callback_(request, HTTPResponse(), ec); } } }
总结
- 连接重试循环:封装在Client类内部,作为连接管理的一部分,用Asio异步延迟实现非阻塞重试
- 请求创建循环:放在业务逻辑层,负责生成请求并交付给Client;请求自身的重试逻辑则放在Client的请求处理方法里
内容的提问来源于stack exchange,提问作者ahmed allam
相关产品推荐
相关产品推荐

