c ++中的异步处理

Kin*_*ing 5 c++ asynchronous daemon aio

一个将永久运行并处理请求的服务器需要一个异步的代码部分,它将执行一些数据库查询并仅在有任何新的更改时才更新.服务器必须永远运行,并且这个函数一次又一次地执行db函数必须异步运行,这样就不会因为每隔'x'分钟更新一次而妨碍服务器.

如何最好地在c ++中异步处理?如何单独设置该功能以在守护程序上运行,以便它根本不阻塞服务器?

Joe*_*oel 5

我强烈建议使用Boost的 ASIO库

您需要一个类来接受新请求,而另一个类需要定期检查更新.两者都可以异步完成工作并使用相同的boost :: asio :: io_service来安排工作.

设置将是

  • 网络异步boost::asio::ip::tcp::acceptor侦听新请求.
  • 一个boost::asio::deadline_time做一个异步等待做检查更新到数据库.

我所理解你所描述的伪代码如下:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <string>

class DatabaseUpdateChecker{
    public:
    DatabaseUpdateChecker(boost::asio::io_service& io, const int& sleepTimeSeconds)
    :timer_(io,boost::posix_time::seconds(sleepTimeSeconds)),sleepSeconds_(sleepTimeSeconds){
        this->timer_.async_wait(boost::bind(&DatabaseUpdateChecker::doDBUpdateCheck,this,boost::asio::placeholders::error));
    };

    protected:
    void doDBUpdateCheck(const boost::system::error_code& error){
        if(!error){
            std::cout << " Checking Database for updates" << std::endl;
            //Reschdule ourself
            this->timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(this->sleepSeconds_));
            this->timer_.async_wait(boost::bind(&DatabaseUpdateChecker::doDBUpdateCheck,this,boost::asio::placeholders::error));
        }
    };
    private:
    boost::asio::deadline_timer timer_;
    int sleepSeconds_;  
};

typedef boost::shared_ptr<boost::asio::ip::tcp::socket> TcpSocketPtr;

class NetworkRequest{
    public: 
    NetworkRequest(boost::asio::io_service& io, const int& port)
    :acceptor_(io,boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(),port)){
        this->start_accept();   
    };  
    protected:
    void start_accept(){
        TcpSocketPtr socketPtr(new boost::asio::ip::tcp::socket(acceptor_.get_io_service()));
        std::cout << "About to accept new connection" << std::endl;
        acceptor_.async_accept(*socketPtr,boost::bind(&NetworkRequest::handle_accept,this,socketPtr,boost::asio::placeholders::error));
    };  
    void handle_accept(TcpSocketPtr socketPtr,const boost::system::error_code& error){
        std::cout << "Accepted new network connection" << std::endl;
        if(!error){
            std::string response("This is a response\n");
            boost::asio::async_write(*socketPtr,boost::asio::buffer(response),
                boost::bind(&NetworkRequest::handle_write,this,boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
        }
        //Start listeing for a new connection
        this->start_accept();
    }   
    void handle_write(const boost::system::error_code& error,size_t size){
        if(!error){
            std::cout << "Wrote out " << size << " bytes to the network connection" << std::endl;
        }

    }   
    private:
    boost::asio::ip::tcp::acceptor acceptor_;
};

int main(int argc, char *argv[]) {
    static const int DB_TIMER_SECONDS=5;
    static const int LISTENING_TCP_PORT=4444;

    std::cout << "About to start" << std::endl;
    boost::asio::io_service io;

    DatabaseUpdateChecker dbChecker(io,DB_TIMER_SECONDS);
    NetworkRequest networkRequestAcceptor(io,LISTENING_TCP_PORT);

    io.run();

    std::cout << "This won't be printed" << std::endl;  
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译上面并运行它将显示数据库更新检查器将在监听TCP端口4444上的连接时每5秒检查一次更新.要查看代码接受新连接,您可以使用telnet/netcat /您最喜欢的网络客户端工具. ...

telnet 127.0.0.1 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
This is a response
Connection closed by foreign host.
Run Code Online (Sandbox Code Playgroud)

如果您发现更新和/或请求的处理需要花费大量时间,那么我会考虑线程化您的应用程序并在其自己的线程中运行每个任务.io_service将安排它必须做的工作,并且在没有更多工作之前不会完成.诀窍是让完成工作的课程在完成后重新安排.

当然,您必须考虑其他人对您问题的评论.我不知道CORBA接口如何使这复杂化,但我认为boost :: asio作为一个异步C++库将是一个很好的决定,并且足够灵活,适合你所描述的内容.