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

io_service.run() isn't blocking. Server is created and then closes instantly

本文关键字:创建 服务器 然后 run service io      更新时间:2023-10-16

所有的boost示例都能工作,直到我自己尝试实现完全相同的东西。我开始认为,必须有一个创建顺序或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示例在客户端本身建立了一个新的成员boosttcp::套接字,而不是将服务器移动到客户端,所以我很困惑。他们还倾向于使用boost版本的std::bind,而不是lambdas等。

因此,有人能简要介绍一下如何创建一个基本的、剥离的异步服务器吗?因为boost示例非常令人困惑,因为每个示例的代码约定不同。我想知道是否有人立即注意到任何会导致我的服务器立即关闭的事情。

谢谢。

我使用以下代码测试了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("Hellon");
        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("Hellon");
    socket.send(buffer(msg, msg.length()));
    */
}

带有Server类和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("Hellon");
                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();
}