io_service.run()没有阻止。服务器已创建,然后立即关闭

时间:2016-08-07 01:54:22

标签: c++ boost boost-asio

所有的提升示例都有效,直到我尝试自己实现完全相同的事情。我开始认为必须有一个创建顺序或io_service所有权才能正确阻止。

我的服务器结构如下:

class Server {
  public:
    Server(unsigned short port)
    : ioService_(), acceptor_(ioService_), socket_(ioService_) { 
      acceptClient(); // begin async accept
    }

    void start(); // runs ioService_.run();

  private:

   void acceptClient();

   asio::io_service ioService_;
   tcp::acceptor acceptor_;
   tcp::socket socket_;
   Cluster cluster_; // essentially just a connection manager
};

acceptClient()函数的工作方式如下:

void Server::acceptClient() {
  acceptor_.async_accept(socket_, [this](const system::error_code& e){
    if(!acceptor_.is_open()) return;
    if(!e) {
      cluster_.add(std::make_shared<Client>(std::move(socket_), cluster_));
    }

    acceptClient();
  });
}

我不确定您是否需要Client类的大纲,因为即使没有客户端服务器也应该运行和阻止。

服务器的创建如下:

try {
  Server server(port);
  server.start(); // this calls the server's member io_service's run();
} catch (const std::exception& e) {
  std::cerr << e.what(); << std::endl;
}

问题是服务器在通话后立即关闭。程序启动然后退出,没有错误。有没有io_service.run()依赖的东西?例如某种形式的异步链接,我已经忘记了?我从boost asio的http服务器设计中学到了这个设计,但我已经用它来完成我的基本用途。问题是一些提升示例在客户端本身建立一个新成员boost tcp :: socket,而不是将服务器移动到客户端,所以我很困惑。他们也倾向于使用boost的std :: bind版本而不是lambdas等等。

所以,任何人都可以给我一个关于如何创建基本的,剥离的异步服务器的简要概述,因为增强示例实际上令人困惑,因为代码约定每个示例都不同。我想知道是否有人立即注意到任何会导致我的服务器立即关闭的内容。

感谢。

1 个答案:

答案 0 :(得分:1)

我使用以下代码测试async_accept,该代码将 Hello 发送到连接到该端口的客户端。至少在您的代码中创建了endpoint对象,acceptor.open(endpoint.protocol())acceptor.bind(endpoint)acceptor.listen()调用。

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

using namespace boost::asio;

void handle_accept(
    io_service * ios,
    ip::tcp::acceptor * acceptor,
    ip::tcp::socket * socket,
    const boost::system::error_code & error)
{
    if (!error) {
        std::string msg("Hello\n");
        socket->send(buffer(msg, msg.length()));

        ip::tcp::socket * temp = new ip::tcp::socket(*ios);
        acceptor->async_accept(*temp,
                               boost::bind(handle_accept,
                                           ios, acceptor, temp,
                                           placeholders::error));
    }
}

int main(void)
{
    io_service ios;
    ip::tcp::socket socket(ios);
    ip::tcp::acceptor acceptor(ios);
    ip::tcp::endpoint endpoint(ip::tcp::v4(), 1500);
    acceptor.open(endpoint.protocol());
    acceptor.set_option(ip::tcp::acceptor::reuse_address(true));
    acceptor.bind(endpoint);
    acceptor.listen();

    acceptor.async_accept(socket,
                          boost::bind(handle_accept,
                                      &ios, &acceptor, &socket,
                                      placeholders::error));
    ios.run();

    /*
    acceptor.accept(socket);
    std::string msg("Hello\n");
    socket.send(buffer(msg, msg.length()));
    */
}

具有服务器类且lambda作为async_accept参数的版本:

#include <boost/asio.hpp>
#include <functional>
#include <string>

using namespace boost::asio;

class Server {
public:
    Server(unsigned short port) : ios(), acceptor(ios), socket(ios), 
                                  endpoint(ip::tcp::v4(), port) {
        acceptor.open(endpoint.protocol());
        acceptor.set_option(ip::tcp::acceptor::reuse_address(true));
        acceptor.bind(endpoint);
        acceptor.listen();
        nsocket = &socket;
    }

    void run() {
        std::function<void (const boost::system::error_code &)> f;
        f = [&f, this] (const boost::system::error_code & error) {
            if (!error) {
                std::string msg("Hello\n");
                nsocket->send(buffer(msg, msg.length()));

                nsocket = new ip::tcp::socket(ios);
                acceptor.async_accept(*nsocket, f);
            }
        };

        acceptor.async_accept(socket, f);
        ios.run();
    }

protected:
    io_service ios;
    ip::tcp::acceptor acceptor;
    ip::tcp::socket socket;
    ip::tcp::endpoint endpoint;

    ip::tcp::socket * nsocket;
};


int main(void)
{
    Server srv(1500);
    srv.run();
}