ブーストasio非同期の分析

コールバックオブジェクトは、io_serviceクラスのrun()メソッドの実行後にのみ呼び出されることに注意してください。そうしないと、システムが非同期操作を完了した場合でも、タスクアクションは発生しません。

さて、それだけです。これが私が持ってきた非同期TCPHelloworldサーバーです。

#include <iostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp>
using namespace boost::asio;
using boost::system::error_code;
using ip::tcp;
struct CHelloWorld_Service{
     CHelloWorld_Service(io_service &iosev)
         :m_iosev(iosev),m_acceptor(iosev, tcp::endpoint(tcp::v4(), 1000))
     {
     }
    void start()
     {
        // 开始等待连接(非阻塞)
         boost::shared_ptr<tcp::socket> psocket(new tcp::socket(m_iosev));
        // 触发的事件只有error_code参数,所以用boost::bind把socket绑定进去
         m_acceptor.async_accept(*psocket,
             boost::bind(&CHelloWorld_Service::accept_handler,this, psocket, _1)
             );
     }
    // 有客户端连接时accept_handler触发
    void accept_handler(boost::shared_ptr<tcp::socket> psocket, error_code ec)
     {
        if(ec) return;
        // 继续等待连接
         start();
        // 显示远程IP
         std::cout << psocket->remote_endpoint().address() << std::endl;
        // 发送信息(非阻塞)
         boost::shared_ptr<std::string> pstr(new std::string("hello async world!"));
         psocket->async_write_some(buffer(*pstr),
             boost::bind(&CHelloWorld_Service::write_handler, this, pstr, _1, _2)
             );
     }
    // 异步写操作完成后write_handler触发
    void write_handler(boost::shared_ptr<std::string> pstr,
         error_code ec, size_t bytes_transferred)
     {
        if(ec)
             std::cout<< "发送失败!" << std::endl;
        else
             std::cout<< *pstr << " 已发送" << std::endl;
     }
private:
     io_service &m_iosev;
     ip::tcp::acceptor m_acceptor;
};
int main(int argc, char* argv[])
{
     io_service iosev;
     CHelloWorld_Service sev(iosev);
    // 开始等待连接
     sev.start();
     iosev.run();
    return 0;
}

この例では、最初にsev.start()を呼び出して、クライアント接続の受け入れを開始します。async_acceptは呼び出しの直後に戻るため、start()メソッドはすぐに完了します。sev.start()が即座に戻ると、iosev.run()の実行が開始されます。iosev.run()メソッドは、非同期コールバックイベントの配布を担当するループです。すべての非同期操作が完了した場合にのみ、戻ります。

ここで問題があります。これは、start()メソッドのm_acceptor.async_accept操作で使用されるtcp :: socketオブジェクトが、非同期操作全体で有効なままであることを確認することです(そうでない場合、システムは下部の非同期操作の半分になります)システムの、そして突然tcp :: socketがなくなったのに気づきました。人々はそれを開きます-_- !!!)、そしてtcp :: socketオブジェクトはクライアントが接続された後もまだ役に立ちます。ここでの解決策は、カウント付きのスマートポインターboost :: shared_ptr <tcp :: socket>を使用し、このポインターをパラメーターとしてコールバック関数にバインドすることです。

クライアント接続が確立されると、start()で指定したコールバック関数accept_handlerが呼び出され、最初にstart()を呼び出して他のクライアントの接続を非同期で待機し続け、次にバインドされたtcp :: socketオブジェクトを使用して通信します。現在のクライアントで。

非同期メソッド(async_write_some)もデータの送信に使用され、非同期送信期間全体でのバッファーの有効性も保証する必要があるため、boost :: bindもboost :: shared_ptr <std :: string>にバインドされます。

おすすめ

転載: blog.csdn.net/qq_23350817/article/details/108573892