提高ASIO状态服务器设计(boost asio stateful server design)

2019-09-18 02:22发布

我正在写一个服务器应用程序boost::asio

  1. 在这里,我实例化一个Server拥有一个io_service
  2. 服务器是由启动server.start()方法,它调用Server::accept() ,并创建一个新的Session 它得到一个新的连接,甚至之前
  3. 呼吁_acceptor.async_accept这就是设置调用回调Session::handler()它执行的握手方法。

现在是好的,甚至得到一个新的客户端之前创建一个插座? 并在此代码的会议是自写一个破坏后"Hello "消息,该消息是在HTTP的情况下好了,但我想进行有状态通信。 所以插座必须async_wait读取后,只写了这个"Hallo " 。 我也想知道这个设计是否好吗? 或有任何设计上的缺陷。

这里不用我的编译代码

class Session: public boost::enable_shared_from_this<Session>, private boost::noncopyable{
  private:
    size_t _id;
    boost::asio::ip::tcp::socket   _socket;
  public:
    typedef boost::shared_ptr<Session> pointer;
    static pointer create(boost::asio::io_service& ios){
      return pointer(new Session(ios));
    }
  private:
  explicit Session(boost::asio::io_service& ios): _socket(ios){
    static size_t counter = 0;
    _id = counter++;
    std::cout << ">> Session " << id() << " constructing" << std::endl;
  }
  public:
    void handler(const boost::system::error_code &ec){
      const std::string message = (boost::format("HTTP/1.1 200 OK\r\nContent-Length: %2%\r\n\r\nHello, %1%!") % id() % (7+boost::lexical_cast<std::string>(id()).length())).str();
      if(!ec){
        boost::asio::async_write(_socket, boost::asio::buffer(message), boost::bind(&Session::write_handler, this));
      }else{
        std::cout << ec.message() << std::endl;
      }
    }
    void write_handler(){

    }
    size_t id() const{
      return _id;
    }
    boost::asio::ip::tcp::socket& socket(){
      return _socket;
    }
    virtual ~Session(){
      std::cout << ">> Session " << id() << " destructing" << std::endl;
    }
    };

class Server: public boost::enable_shared_from_this<Server>, private boost::noncopyable{
  private:
    boost::asio::io_service        _ios;
    boost::asio::ip::tcp::acceptor _acceptor;
  public:
    explicit Server(boost::asio::ip::tcp::endpoint& endpoint):_acceptor(_ios, endpoint){

    }
    void start(){
      accept();
      _ios.run();
    }
    void accept(){
      std::cout << "accepting " << std::endl;;
      Session::pointer session = Session::create(_ios);
      _acceptor.async_accept(session->socket(), boost::bind(&Server::handler, this, session, boost::asio::placeholders::error));
    }
    void handler(Session::pointer session, const boost::system::error_code &ec){
      if(!ec){
        session->handler(ec);
      }else{
        //possible destroy session ? but how to destroy a shared pointer ?
      }
      accept();
    }
};


int main(){  
  const unsigned int port = 5050;
  boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);

  Server server(endpoint);
  server.start();

  return 0;
}

Answer 1:

整体设计看起来不错,但也有少数实现错误:

  • Session::handler() message ,底层缓冲器提供async_write()可能会超出范围之前async_write()被调用。 这是一个违反的API所要求的保证。 考虑制定message的成员变量的Session ,或使其static成员函数中。 这是从文档相关的摘录:

    尽管缓冲器对象可以根据需要复制,底层存储块的所有权由呼叫者,必须保证它们保持有效,直到处理程序被调用保留。 下面是从文档相关的摘录:

  • 对于对象继承boost::enable_shared_from_this ,使用shared_from_this()而不是this传递实例句柄时指针boost::bind 。 否则,它是可能的对象实例指向this之前,可以在处理器运行删除。

此外,以解决中的代码注释的问题Server::handler()如果出现错误,该Session将一旦处理程序返回,因为它是通过管理被删除boost::shared_ptr



文章来源: boost asio stateful server design