boost asio状态服务器设计 [英] boost asio stateful server design

查看:209
本文介绍了boost asio状态服务器设计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


  1. 我实例化一个拥有 io_service

  2. 服务器是由调用 Server :: accept() server.start()方法启动的, c $ c> Session 甚至在它获得新连接之前

  3. 调用 _acceptor.async_accept thats设置了一个回调,它调用 Session :: handler()方法来执行握手。

  1. Here I instantiate a Server that owns an io_service
  2. Server is started by server.start() method which calls Server::accept() and that creates a new Session even before it gets a new connection
  3. Calls _acceptor.async_accept thats set a callback that calls Session::handler() method which does the handshaking.

现在是否可以在获得新客户端之前创建套接字?
并且在这个代码中,会话在写入一个Hello之后被自动破坏。在HTTP的情况下这是好的,但是我想进行有状态通信。所以socket必须 async_wait 才能读取,因为它只是写了这个Hallo。也想知道这个设计是否可以吗?

Now is it okay to create a socket even before getting a new client ? and in this code the Session is auto destructed after writing an "Hello " Message which is Okay in case of HTTP, But I want to carry on a Stateful Communication. so socket must async_wait for reading after it just wrote this "Hallo ". also I'd like to know whether this design is okay ? or it Has any design flaw.

这里是我的可编译代码

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;
}


推荐答案

整体设计看起来不错,但有一些实现错误:

The overall design looks okay, but there are a few implementation errors:


  • Session :: handler c>: message ,底层缓冲提供 async_write() ,可能会超出范围 async_write / code>。这是违反API要求的保证。考虑为 Session 创建消息的一个成员变量,或者使它 static 在成员函数内。这是文档中的相关摘录:

  • Session::handler(): message, the underlying buffer provided async_write(), may go out of scope before async_write() is invoked. This is a violation of the guarantee required by the API. Consider making message a member variable for Session, or make it static within the member function. This is the relevant excerpt from the documentation:


虽然可以根据需要复制buffers对象,但是底层内存块的所有权保留调用者必须保证它们在调用处理程序之前保持有效。下面是文档中的相关摘录:

Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called. Here is the relevant excerpt from the documentation:


  • boost :: enable_shared_from_this 时,使用 shared_from_this()而不是 this c $ c> boost :: bind 。否则,可能会在处理程序运行之前删除 this 指向的对象实例。

  • For objects inheriting from boost::enable_shared_from_this, use shared_from_this() instead of the this pointer when passing the instance handle to boost::bind. Otherwise, it is possible that the object instance pointed to by this may be deleted prior to the handler running.

    此外,要解决 Server :: handler()中代码注释中的问题,如果发生错误, 会话将在处理程序返回后被删除,因为它通过 boost :: shared_ptr 管理。

    Also, to address the question in the code comment within the Server::handler(), if an error occurs, the Session will be deleted once the handler returns since it is managed via a boost::shared_ptr.

    这篇关于boost asio状态服务器设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆