gpt4 book ai didi

c++ - 持久的 ASIO 连接

转载 作者:可可西里 更新时间:2023-11-01 02:47:13 26 4
gpt4 key购买 nike

我正在做一个项目,我需要能够使用一些持久性来长时间与不同的服务器通信。该服务器将具有相当高的吞吐量。我无法找到正确设置持久连接的方法。我能想到的最好的方法是创建一个持久连接类。理想情况下,我会连接到服务器一次,并在收到信息时执行 async_writes。并阅读返回给我的信息。不过,我认为我的类(class)结构不正确。

这是我现在构建的:

persistent_connection::persistent_connection(std::string ip, std::string port):
io_service_(), socket_(io_service_), strand_(io_service_), is_setup_(false), outbox_()
{
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(ip,port);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ip::tcp::endpoint endpoint = *iterator;
socket_.async_connect(endpoint, boost::bind(&persistent_connection::handler_connect, this, boost::asio::placeholders::error, iterator));
io_service_.poll();
}

void persistent_connection::handler_connect(const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
{
if(ec)
{
std::cout << "Couldn't connect" << ec << std::endl;
return;
}
else
{
boost::asio::socket_base::keep_alive option(true);
socket_.set_option(option);
boost::asio::async_read_until(socket_, buf_ ,"\r\n\r\n", boost::bind(&persistent_connection::handle_read_headers, this, boost::asio::placeholders::error));
}
}

void persistent_connection::write(const std::string &message)
{
write_impl(message);
//strand_.post(boost::bind(&persistent_connection::write_impl, this, message));
}

void persistent_connection::write_impl(const std::string &message)
{
outbox_.push_back(message);
if(outbox_.size() > 1)
{
return;
}
this->write_to_socket();
}

void persistent_connection::write_to_socket()
{
std::string message = "GET /"+ outbox_[0] +" HTTP/1.0\r\n";
message += "Host: 10.1.10.120\r\n";
message += "Accept: */*\r\n";
boost::asio::async_write(socket_, boost::asio::buffer(message.c_str(), message.size()), strand_.wrap(
boost::bind(&persistent_connection::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));

}

void persistent_connection::handle_write(const boost::system::error_code& ec, std::size_t bytes_transfered)
{
outbox_.pop_front();
if(ec)
{
std::cout << "Send error" << boost::system::system_error(ec).what() << std::endl;
}
if(!outbox_.empty())
{
this->write_to_socket();
}
boost::asio::async_read_until(socket_, buf_ ,"\r\n\r\n",boost::bind(&persistent_connection::handle_read_headers, this, boost::asio::placeholders::error));
}

我将由此发送的第一条消息似乎发送正常,服务器收到它,并以有效响应进行响应。不幸的是,我看到两个问题:

1) 在执行 async_write 命令后,我的 handle_write 从未被调用,我不知道为什么。2) 程序从不读取响应,我猜这与#1 有关,因为在该函数发生之前不会调用 asyn_read_until。3) 我还想知道是否有人可以告诉我为什么我注释掉的 strand_.post 调用不起作用。

我猜这大部分是由于我不了解我应该如何使用我的 io_service,所以如果有人能给我任何指示,我将不胜感激。如果您需要任何其他信息,我很乐意提供更多信息。

谢谢

编辑调用写入:

int main()
{
persistent_connection p("10.1.10.220", "80");
p.write("100");
p.write("200");
barrier b(1,30000); //Timed mutex, waits for 300 seconds.
b.wait();
}

void persistent_connection::handle_read_headers(const boost::system::error_code &ec)
{
std::istream is(&buf_);
std::string read_stuff;
std::getline(is,read_stuff);
std::cout << read_stuff << std::endl;
}

最佳答案

所描述的行为是 io_service_ 的事件循环不再被处理的结果。

构造函数调用io_service::poll()它将运行准备好运行的处理程序,并且不会阻塞等待工作完成,其中 io_service::run()将阻塞直到所有工作完成。因此,在轮询时,如果连接的另一端未写入任何数据,则可能没有准备好运行的处理程序,执行将从 poll() 返回。

关于线程,如果每个连接都会有自己的线程,并且通信是半双工协议(protocol),比如HTTP,那么应用代码如果是同步写的可能会更简单。另一方面,如果每个连接都有自己的线程,但代码是异步编写的,那么请考虑处理从事件循环中抛出的异常。可能值得阅读 Boost.Asio 的 effect of exceptions thrown from handlers .

此外,persistent_connection::write_to_socket() 引入了未定义的行为。调用时 boost::asio::async_write() ,据记载,调用者保留缓冲区的所有权,并且必须保证缓冲区在调用处理程序之前保持有效。在这种情况下,message 缓冲区是一个自动变量,其生命周期可能会在 persistent_connection::handle_write 处理程序被调用之前结束。一种解决方案是通过将 message 设为成员变量来更改其生命周期以匹配 persistent_connection 的生命周期。

关于c++ - 持久的 ASIO 连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16061420/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com