You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:23:09