boost::asio async_accept 杀死 ioservice

Posted

技术标签:

【中文标题】boost::asio async_accept 杀死 ioservice【英文标题】:boost::asio async_accept kill ioservice 【发布时间】:2014-03-05 11:00:17 【问题描述】:

你能帮我解决一点小问题吗?

我有 2 节课: 表格1 async_srv

当我启动应用程序时,Form1 创建 async_srv 实例。 并听我的套接字,所有收到的数据都发送到主类并从她那里返回答案。 当得到-1时,我想要destoy接受器/服务/线程和我的应用程序。 但这行不通。 有什么建议吗?

我的 async_srv.h

#include "Form1.h"
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
typedef boost::shared_ptr<boost::asio::ip::tcp::socket> socket_ptr;
typedef boost::shared_ptr<boost::asio::ip::tcp::acceptor> acc_ptr;


class async_srv

    private:
    boost::thread* srv_thread;
    boost::asio::streambuf response;
    std::stringstream s;
    int stop;
    TForm* ourForm;
    boost::shared_ptr<boost::asio::io_service> m_ioservice;

    protected:
    void start();
    void start_accept(acc_ptr acc,socket_ptr sock);
    void handle_accept(acc_ptr acc, socket_ptr sock);

    public:
    __fastcall async_srv(TForm* Form1);
    void kill(); 

;

我的 async_srv.cpp

fastcall async_srv::async_srv(TForm* Form1): m_ioservice(boost::make_shared<boost::asio::io_service>())

 //create Pointer to main form
ourForm = Form1;
 //create thread to async recieve for realease this class
srv_thread = new boost::thread(boost::bind(&async_srv::start, this));


void async_srv::start()

 //create acceptor, and socket.
acc_ptr acc(new boost::asio::ip::tcp::acceptor(*m_ioservice, ep));
socket_ptr sock(new boost::asio::ip::tcp::socket(*m_ioservice));

//start_accept
start_accept(acc,sock);
m_ioservice->run();


void async_srv::start_accept(acc_ptr acc,socket_ptr sock)

  // async accept
  acc->async_accept(*sock, boost::bind(&async_srv::handle_accept, this, acc, sock));


void async_srv::handle_accept(acc_ptr acc, socket_ptr sock)

    //loop for recieve data
    while (boost::asio::read(*sock, response, boost::asio::transfer_at_least(1), error))
    s << &response;

    if (s.str() != "")
      
       //recieve answer from main
      stop = ourForm->update(s.str());
         if(stop == -1)
                  
                               //kill our class and application
                  acc->close();
                  kill();
                  Application->Terminate();
                  return;
                  
      

    s.str(std::string());
    response.consume(response.size());
    start_accept(acc,sock);


void async_srv::kill()

m_ioservice->stop();
srv_thread->~thread();

【问题讨论】:

手动调用srv_thread 的析构函数听起来是个非常糟糕的主意。另外,您能否发布SSCCE,因为目前尚不清楚您的async_src 课程是如何使用的。 杀死线程不是主要问题,我可以使用中断而不是析构函数。主要问题,服务在 stop() 之后不会停止接受 async_src 用于从 tcp/ip 套接字接收数据。 你确定kill()被调用了吗?看一下代码,如果sock 在没有任何数据的情况下关闭,或者ourForm-&gt;update() 在链中第一次被调用时返回除-1 之外的任何值,则在start_accept()handle_accept() 之间形成一个紧密的异步链由于sock 的状态导致操作失败。接受操作将立即失败,因为sock 已打开,读取操作将立即失败,因为文件结束,将s.str() 留空,不再查询表单。 我的错误是在我的句柄上调用 start_accept 方法,只需替换 "start_accept(acc,sock)" 以创建新的 "async->accept",一切正常。 【参考方案1】:

如果您想停止接受新连接 - 让接受者成为成员并在需要时关闭它:

void async_srv::kill()

  // avoid closing from another thread
  m_acceptor.get_io_service().post(()[this]  m_acceptor->close(); );

如果m_ioservice 仅服务于接受器,关闭它将破坏async_accept--&gt;handle_accept--&gt;... 链并最终使m_ioservice::run() 退出,因为它会耗尽工作。 (当然,你不应该打电话给~thread。)

【讨论】:

我使用了 boost 1.39,我的接受器没有方法 get_io_service() @user2393500 它被称为io_service() 我知道,对不起我的错误。 IDE 不会在提示中显示此方法。 我已经关闭接受者:if(stop == -1) acc->close();杀();应用程序->终止(); @user2393500 我猜问题出在代码的其他地方。尝试在调试器中调试它 - 设置断点,单步执行代码等。

以上是关于boost::asio async_accept 杀死 ioservice的主要内容,如果未能解决你的问题,请参考以下文章

boost::asio::ip::tcp::acceptor 在使用 async_accept 接收连接请求时终止应用程序

boost::asio async_accept 杀死 ioservice

Boost asio async_accept 在 Windows 下工作,但在 FreeBSD 下失败。怎么了?

Boost asio 获取“错误代码:125 操作已取消”[关闭]

将 Boost.Log 与 Boost.Asio 服务一起使用

使用 boost::asio::async_wait_until 和 boost::asio::streambuf