Ich habe vor kurzem ein Problem mit boost :: asio asynchronen Aufgaben festgestellt. Ich möchte einen Zeiger auf ein Objekt zurückgeben, das auf einen Port hört. Es funktioniert, wenn ich die Methode socket.read_some verwende, aber diese Methode blockiert mein Haupt und ich möchte meine MyClass :: create-Methode zurückgeben.Boost Asio - Warum starten meine asynchronen Operationen nicht?
Also versuchte ich einen async_read-Aufruf, aber ich sah, dass innerhalb meiner read() -Methode keine asynchronen Aufgaben gestartet werden. Ich habe versucht, herauszufinden, was das Problem verursachen könnte, aber ich sehe keine Lösung für dieses Problem.
Hier ist mein Code, hier ist es nicht mit einem async_read aber mit einem async_wait, und das gleiche Problem erscheint, wird der Timer nicht gestartet.
Danke für jede Hilfe, die ich bekommen könnte.
Die Header-Datei:
#ifndef MYCLASS_HPP
#define MYCLASS_HPP
#include <memory>
#include <boost/asio.hpp>
class MyClass
{
public:
MyClass(boost::asio::io_service& ios);
void read();
void read_handler(const boost::system::error_code& error);
static std::shared_ptr<MyClass> create(std:: string const & host, uint16_t port);
bool connect (std::string const & host, uint16_t port);
void connect_handler(const boost::system::error_code& error);
boost::asio::ip::tcp::socket m_socket;
bool m_flag;
std::vector<uint8_t> m_buffer;
};
#endif
Quelldatei:
#include "MyClass.hpp"
#include <boost/bind.hpp>
MyClass::MyClass(boost::asio::io_service& ios)
:m_flag(false), m_socket(ios), m_buffer(20)
{
}
void MyClass::read_handler(const boost::system::error_code& er)
{
std::cout << "Timer waited 5 sec" << std::endl;
}
void MyClass::read()
{
boost::asio::deadline_timer t(m_socket.get_io_service(),boost::posix_time::seconds(5));
t.async_wait(boost::bind(&MyClass::read_handler,this,boost::asio::placeholders::error));
m_socket.get_io_service().run();//Should make the io_service wait for all asynchronous tasks to finish
std::cout << "This message should be displayed after the wait" << std::endl;
}
void MyClass::connect_handler(const boost::system::error_code& error)
{
if(!error)
{
std::cout << "Connection done" << std::endl;
m_flag = 1;
}
else
{
std::cout << "Error in connection: " << error.message() << std::endl;
}
}
//connect method
bool MyClass::connect(std::string const & host, uint16_t port)
{
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string(host),port);
m_socket.async_connect(endpoint,
boost::bind(&MyClass::connect_handler, this,
boost::asio::placeholders::error));
m_socket.get_io_service().run();//Wait async_connect and connect_handler to finish
if (m_flag == 0) return false;
else return true;
}
std::shared_ptr<MyClass> MyClass::create(std:: string const & host, uint16_t port)
{
boost::asio::io_service ios;
std::shared_ptr<MyClass> ptr(new MyClass(ios));
bool bol = ptr->connect(host, port);
ptr->read();
//while(1){}
if(bol == true)
{
//connection success, reading currently listening, pointer is returned to the user
return ptr;
}
else
{
//connection failure, pointer is still returned to the user but not listening as he's not connected
return ptr;
}
}
Und mein Haupt:
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/asio.hpp>
#include "MyClass.hpp"
int main()
{
try
{
std::cout << "Creation of instance" << std::endl;
std::shared_ptr <MyClass> var = MyClass::create("127.0.0.1", 8301);
std::cout << "Instance created" << std::endl;
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
return 0;
}
Weil Sie in 'MyClass :: create' einen temporären' boost :: asio :: io_service' erstellen, der zerstört wird, bevor Sie 'run' oder' poll' darauf aufrufen können. Versuchen Sie es in 'main' zu erstellen, übergeben Sie es an' MyClass :: create' und rufen Sie danach 'run()' darauf auf. – kenba
@kenba anscheinend hatten Sie recht, aber ich habe auch einen Reset() auf meinem io_service vergessen, ich werde versuchen, ihn am Leben zu halten – PsykoBabar
@PsykoBabar ist es Ihre Absicht, 'io_service :: run' wieder in' read() 'aufzurufen ? Um den 'io_service' am Leben zu erhalten, tun Sie was @kenba vorschlägt, rufen Sie aber' read() 'von' connect_handler' auf. Auf diese Weise wird 'read()' aufgerufen, nachdem die Verbindung erfolgreich hergestellt wurde. Gerade jetzt wird 'read()' aufgerufen, ob eine Verbindung besteht oder nicht. Ich weiß, dass dies wahrscheinlich Debug-Code ist und Sie lesen nicht aus dem Socket in 'read()', aber Sie müssen auf keinen Fall den 'io_service' zurücksetzen und' run' erneut aufrufen. – aichao