gpt4 book ai didi

c++ - 亚信 : Prevent asynchronous client from being deleted?

转载 作者:行者123 更新时间:2023-11-28 05:46:11 26 4
gpt4 key购买 nike

我有以下代码,试图编写一个异步客户端。

问题是在 main() 中,Client 在 try-catch block 中被删除,因为执行离开了作用域。

我试图想出解决这个问题的方法,比如添加一个while(true),但我不喜欢这种方法。另外,我不喜欢 getchar()

由于调用的异步性质,connect()loop() 都会立即返回。

我该如何解决这个问题?

#include <iostream>
#include <thread>
#include <string>

#include <boost\asio.hpp>
#include <Windows.h>

#define DELIM "\r\n"

using namespace boost;


class Client {
public:
Client(const std::string& raw_ip_address, unsigned short port_num) :
m_ep(asio::ip::address::from_string(raw_ip_address), port_num), m_sock(m_ios)
{
m_work.reset(new asio::io_service::work(m_ios));
m_thread.reset(new std::thread([this]() {
m_ios.run();
}));

m_sock.open(m_ep.protocol());
}

void connect()
{
m_sock.async_connect(m_ep, [this](const system::error_code& ec)
{
if (ec != 0) {
std::cout << "async_connect() error: " << ec.message() << " (" << ec.value() << ") " << std::endl;
return;
}

std::cout << "Connection to server has been established." << std::endl;
});
}

void loop()
{
std::thread t = std::thread([this]()
{
recv();
});

t.join();
}

void recv()
{
asio::async_read_until(m_sock, buf, DELIM, [this](const system::error_code& ec, std::size_t bytes_transferred)
{
if (ec != 0) {
std::cout << "async_read_until() error: " << ec.message() << " (" << ec.value() << ") " << std::endl;
return;
}

std::istream is(&buf);
std::string req;
std::getline(is, req, '\r');
is.get(); // discard newline

std::cout << "Received: " << req << std::endl;

if (req == "alive") {
recv();
}
else if (req == "close") {
close();
return;
}
else {
send(req + DELIM);
}
});
}

void send(std::string resp)
{
auto s = std::make_shared<std::string>(resp);
asio::async_write(m_sock, asio::buffer(*s), [this, s](const system::error_code& ec, std::size_t bytes_transferred)
{
if (ec != 0) {
std::cout << "async_write() error: " << ec.message() << " (" << ec.value() << ") " << std::endl;
return;
}
else {
recv();
}
});
}

void close()
{
m_sock.close();
m_work.reset();
m_thread->join();
}

private:
asio::io_service m_ios;
asio::ip::tcp::endpoint m_ep;
asio::ip::tcp::socket m_sock;
std::unique_ptr<asio::io_service::work> m_work;
std::unique_ptr<std::thread> m_thread;

asio::streambuf buf;
};

int main()
{
const std::string raw_ip_address = "127.0.0.1";
const unsigned short port_num = 8001;

try {
Client client(raw_ip_address, port_num);
client.connect();
client.loop();
}
catch (system::system_error &err) {
std::cout << "main() error: " << err.what() << " (" << err.code() << ") " << std::endl;
return err.code().value();
}
return 0;
}

最佳答案

您还没有真正理解 asio 的工作原理。通常在主线程中,您将调用 io_service::run() (它将处理所有异步事件。)

确保Client的生命周期, 使用 shared_ptr<>并确保在处理程序中使用此共享指针。例如..

io_service service;

{
// Create the client - outside of this scope, asio will manage
// the life time of the client
auto client = make_shared<Client>(service);
client->connect(); // setup the connect operation..
}
// Now run the io service event loop - this will block until there are no more
// events to handle
service.run();

现在您需要重构您的 Client代码:

class Client : public std::enable_shared_from_this<Client> {

Client(io_service& service): socket_(service) ...
{ }

void connect() {
// By copying the shared ptr to the lambda, the life time of
// Client is guaranteed
socket_.async_connect(endpoint_, [self = this->shared_from_this()](auto ec)
{
if (ec) {
return;
}

// Read
self->read(self);
});
}

void read(shared_ptr<Client> self) {
// By copying the shared ptr to the lambda, the life time of
// Client is guaranteed
asio::async_read_until(socket_, buffer_, DELIM, [self](auto ec, auto size)
{
if (ec) {
return;
}
// Handle the data
// Setup the next read operation
self->read(self)
});
}
};

您有一个用于读取操作的线程——这不是必需的。这将注册一个异步读取操作并立即返回。您需要注册一个新的读取操作才能继续读取套接字(正如我所描绘的那样......)

关于c++ - 亚信 : Prevent asynchronous client from being deleted?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36152667/

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