问题描述
我正在使用Asio来处理我的网络课程。 我已经困扰了一段时间,但我不知道为什么。
首先,代码:
// .h
#pragma once
#include <asio.hpp>
class Connection : public std::enable_shared_from_this<Connection>
{
public:
static std::shared_ptr<Connection> create(asio::io_context& IoContext);
asio::ip::tcp::socket& getSocket();
void start();
private:
Connection(asio::io_context& IoContext);
void startReading();
void sendPacket(std::string Packet);
void handle_read(const asio::error_code& error,size_t bytes);
void handle_write(const asio::error_code& error,size_t bytes);
void disconnect();
asio::ip::tcp::socket socket;
char packet[4096];
bool started;
};
class Network
{
public:
Network(asio::io_context& IoContext,unsigned short Port);
void startServer();
private:
void startAccept();
void handle_accept(std::shared_ptr<Connection> connection,const asio::error_code& error);
asio::io_context& ioContext;
asio::ip::tcp::acceptor acceptor;
bool started;
std::vector<std::shared_ptr<Connection>> connections;
};
// .cpp
Connection::Connection(asio::io_context& IoContext)
: socket(IoContext),started(false),packet("")
{
}
std::shared_ptr<Connection> Connection::create(asio::io_context& IoContext)
{
return std::shared_ptr<Connection>(new Connection(IoContext));
}
asio::ip::tcp::socket& Connection::getSocket()
{
return socket;
}
void Connection::start()
{
std::cout << "Connection::start();" << std::endl;
if (!started)
{
startReading();
started = true;
}
}
void Connection::sendPacket(std::string Packet)
{
socket.async_send(asio::buffer(Packet),[this](const asio::error_code& error,size_t bytes)
{ handle_write(error,bytes); });
}
void Connection::startReading()
{
socket.async_receive(asio::buffer(packet),size_t bytes)
{ handle_read(error,bytes); });
}
void Connection::handle_write(const asio::error_code& error,size_t bytes)
{
std::cout << "WRITE : " << error.message() << " size : " << bytes << std::endl;
}
void Connection::handle_read(const asio::error_code& error,size_t bytes)
{
if (error)
{
std::cout << "error:" << error.message();
disconnect();
}
else
{
if (bytes > 0)
{
packet[bytes] = 0;
std::string response = ...;
sendPacket(response);
}
}
}
Network::Network(asio::io_context& IoContext,unsigned short Port)
: ioContext(IoContext),acceptor(ioContext,asio::ip::tcp::endpoint(asio::ip::tcp::v4(),Port)),started(false)
{
std::cout << "Server::Server();" << std::endl;
}
void Network::startServer()
{
std::cout << "Server::startServer();" << std::endl;
if (!started)
{
startAccept();
started = true;
}
}
void Network::startAccept()
{
std::cout << "Server::startAccept();" << std::endl;
std::shared_ptr<Connection> connection = Connection::create(ioContext);
connections.push_back(connection);
asio::error_code er;
acceptor.async_accept(connection->getSocket(),std::bind(&Network::handle_accept,this,connection,er));
}
void Network::handle_accept(std::shared_ptr<Connection> connection,const asio::error_code& error)
{
std::cout << "Server::handle_accept();" << std::endl;
if (!error)
{
std::cout << "Ok" << std::endl;
connection->start();
}
startAccept();
}
(我从cpp中删除了不必要的功能,以使其更加简洁,如果缺少某些内容,请不要感到惊讶)
基本上,当我从handle_read函数sendPacket(something)
崩溃时,它会崩溃。
我找到了两个解决方法:
- 创建并使用成员
std::string
,然后handle_read(...)
中的代码变为
if (bytes > 0)
{
packet[bytes] = 0;
std::string response = ...;
sendPacket(my_member_string);
}
- 或我在
std::string*
中创建一个sendPacket(...)
:
void Connection::sendPacket(std::string Packet)
{
std::string *copy;
socket.async_send(asio::buffer(copy),bytes); });
}
不删除它(如果这样做,它会以相同的方式崩溃)。
所以,我的问题是:response
为什么引起崩溃?我读过很多关于“生命周期”的文章,您能告诉我更多吗? response
一生中的这段代码中真正发生了什么?
另外,如果不是上述方法之一,那么解决此错误的干净方法是什么?
顺便说一句,我不使用Boost。
先谢谢您
解决方法
您不应使用 ..._ async 函数在您的lambda中捕获[this]
指针。因为lambda将超过 this 指针,而 this 将指向lambda调用中的无效地址。
使用[self=shared_from_this()]
并在lambda中与 self 一起使用,这样该对象将通过异步调用与共享指针一起使用。