Boost 异步写入延迟后未调用的回调

Boost 异步写入延迟后未调用的回调,boost,tcp,callback,boost-asio,asyncsocket,Boost,Tcp,Callback,Boost Asio,Asyncsocket,睡眠一秒钟后,我对async\u write\u some的回调没有被调用。如果每次写入都启动io\u服务worker线程,为什么不调用回调 标题 boost::system::error_code error_1; boost::shared_ptr <boost::asio::io_service> io_service_1; boost::shared_ptr <boost::asio::ip::tcp::socket> socket_1; 这很奇怪,原因有很多

睡眠一秒钟后,我对
async\u write\u some
的回调没有被调用。如果每次写入都启动
io\u服务
worker线程,为什么不调用回调

标题

boost::system::error_code error_1;
boost::shared_ptr <boost::asio::io_service> io_service_1;
boost::shared_ptr <boost::asio::ip::tcp::socket> socket_1;
这很奇怪,原因有很多

  • 您不应该为每个操作“运行”io_服务。相反,在发布操作时稳定地运行它们。可以选择使用
    io\u service::work
    来防止运行返回
  • 您不应该(必须)为每个操作创建线程。如果有什么不同的话,那就是同步问题的秘诀()
  • 在返回后再次运行
    io\u服务时(无错误),您应根据文档()首先调用
    reset()
  • 您破坏了一个未分离的线程——可能是在它完成之前。如果您使用了
    std::thread
    ,这甚至会导致程序立即异常终止。不连接未分离的线程是一种不好的做法(我要补充的是,在线程终止时不显式同步就使用分离的线程是不可靠的)。看
我想补充一下这些最重要的问题

  • 使用诸如
    socket\u 1
    之类的名称(只需将其命名为
    socket\u
    ,并用描述性名称实例化另一个对象以包含另一个
    socket\u
    )。我不确定,但这个问题确实让人怀疑这些甚至可能是全局变量。(我希望不是这样)
  • 抛出原始整数,真的吗
  • 破坏
    io_服务
    ,而从不检查工作线程是否已完成,这可能会导致数据争用
  • 详情如下:

    传递对超出范围的参数
    数据的引用。当异步操作完成时,它将是一个悬空引用

  • 这里存在一些明显的复制/粘贴问题:

    if (socket_1.get() == NULL || !socket_1->is_open())
    {
        WARNING << "serial_port_1 is not open";
        return;
    }
    

    感谢sehe的帮助和祈祷,我的问题现在已经解决了

    open\u eth\u socket
    中的这一行:

    boost::thread t(boost::bind(&boost::asio::io_service::run, *&io_service_1));
    
    现在是:

    boost::shared_ptr <boost::thread>  io_service_1_thread;    // in header
    
    if (io_service_1_thread.get()) io_service_1_thread->interrupt();
    io_service_1_thread.reset(new boost::thread (boost::bind(&eth_socket::run_io_service_1, this)));
    
    boost::共享\u ptr io\u服务\u 1\u线程;//在标题中
    如果(io_服务线程.get())io_服务线程->中断();
    io_服务_1_线程.reset(新的boost::thread(boost::bind(ð_socket::run_io_服务_1,this));
    
    我增加了这个功能:

    void eth_socket::run_io_service_1 (void)
    {
      while (true)  // work forever
      {
        boost::asio::io_service::work work(*io_service_1);
        io_service_1->run();
        io_service_1->reset();   // not sure if this will cause problems yet
        INFO << "io_service_1 run complete";
        boost::this_thread::sleep (boost::posix_time::milliseconds (100));
      }
    
        return;
    }
    
    void eth_socket::运行_io_服务_1(void)
    {
    while(true)//永远工作
    {
    boost::asio::io_服务::工作(*io_服务_1);
    io_服务_1->run();
    io_服务_1->reset();//不确定这是否会导致问题
    
    信息说明当
    write\u data
    与之前的读取重叠时,这就留下了数据争用的问题。稍后我将链接到常见的解决方案。谢谢。我想我的问题是
    io\u服务和线程。所以
    \u work
    线程总是在运行?在回调中我应该有
    io\u 1->reset()
    并在我连接后启动
    io_服务
    工作线程?我认为工作线程在回调上没有工作,因此每次写入时我都需要启动它…请阅读示例代码/我没有无故编写示例。如果您错过了,可能需要额外的后台链接:(它指的是第一个子弹)哦,我以前没有看到过,但是
    *&io\u service\u 1
    肯定是错的。这是一个重复。你可能(毫无用处地)指的是
    和*io\u service\u
    。但是
    boost::bind
    支持
    共享的\u ptr
    很好,直接-让它更安全)
    boost::thread t(boost::bind(&boost::asio::io_service::run, *&io_service_1));                
    
    _sock.async_write_some(
            ba::buffer(data.c_str(), data.size()),
    
    if (socket_1.get() == NULL || !socket_1->is_open())
    {
        WARNING << "serial_port_1 is not open";
        return;
    }
    
    #include <boost/asio.hpp>
    #include <boost/thread.hpp>
    #include <iostream>
    
    namespace ba = boost::asio;
    using ba::ip::tcp;
    using boost::system::error_code;
    
    #define ERROR   std::cerr
    #define WARNING std::cerr
    #define INFO    std::cerr
    
    struct eth_socket {
    
        ~eth_socket() {
            _work.reset();
            if (_worker.joinable())
                _worker.join(); // wait
        }
    
        void open(std::string address);
        void write_data(std::string data);
    
      private:
        void connected(error_code error) {
            if (error)
                ERROR << "Connect failed: " << error << "\n";
            else
                INFO << "Connected to " << _sock.remote_endpoint() << "\n";
        }
        void written(error_code error, size_t bytes_transferred);
    
      private:
        ba::io_service _svc;
        boost::optional<ba::io_service::work> _work{ _svc };
        boost::thread _worker{ [this] { _svc.run(); } };
    
        std::string _data;
    
        unsigned short _port = 6767;
        tcp::socket _sock{ _svc };
    };
    
    void eth_socket::open(std::string address) {
        tcp::endpoint remote_endpoint(ba::ip::address::from_string(address), _port);
    
        _sock.async_connect(remote_endpoint, boost::bind(&eth_socket::connected, this, _1));
    }
    
    void eth_socket::write_data(std::string data) {
        _data = data;
    
        _sock.async_write_some(ba::buffer(_data), boost::bind(&eth_socket::written, this, _1, _2));
    }
    
    void eth_socket::written(error_code error, size_t bytes_transferred) {
        INFO << "data written to " << _sock.remote_endpoint() << " " << error.message() << ";"
             << "bytes_transferred = " << bytes_transferred << "\n";
    }
    
    int main() {
        {
            eth_socket s;
            s.open("127.0.0.1");
    
            s.write_data("Hello"); // callback called
            s.write_data("Hello"); // callback called
            s.write_data("Hello"); // callback called
            boost::this_thread::sleep_for(boost::chrono::seconds(1));
            s.write_data("Hello"); // callback not called after sleep
    
        } // orderly worker thread join here
    }
    
    boost::thread t(boost::bind(&boost::asio::io_service::run, *&io_service_1));
    
    boost::shared_ptr <boost::thread>  io_service_1_thread;    // in header
    
    if (io_service_1_thread.get()) io_service_1_thread->interrupt();
    io_service_1_thread.reset(new boost::thread (boost::bind(&eth_socket::run_io_service_1, this)));
    
    void eth_socket::run_io_service_1 (void)
    {
      while (true)  // work forever
      {
        boost::asio::io_service::work work(*io_service_1);
        io_service_1->run();
        io_service_1->reset();   // not sure if this will cause problems yet
        INFO << "io_service_1 run complete";
        boost::this_thread::sleep (boost::posix_time::milliseconds (100));
      }
    
        return;
    }