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

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

问题描述

我写一个服务器应用程序的boost :: ASIO


  1. 在这里,我实例化一个服务器拥有一个 io_service对象

  2. 服务器是由开始server.start()方法,它调用服务器::接受()和创造一个新的会话 之前就得到一个新的连接

  3. 呼叫 _acceptor.async_accept 多数民众赞成设置调用由它来完成握手会话::处理器()方法回调

现在是不是都没问题,即使得到一个新的客户端之前创建套接字?
在这code中的Session是写一个你好消息这是在HTTP的情况下,奥凯后自动销毁,但我想进行有状态通信。所以插座必须 async_wait 阅读后,它只是写了这个。我也想知道这个设计是否好吗?或有任何设计缺陷。

下面去我可编译code

 堂课:公众的boost :: enable_shared_from_this<会议>中私人的boost :: {不可复制
  私人的:
    为size_t _id;
    提高:: ASIO ::知识产权:: TCP ::插座_socket;
  上市:
    TYPEDEF提高:: shared_ptr的<会议>指针;
    静态指针创建(提高:: ASIO :: io_service对象和放大器; IOS){
      返回指针(新的Session(IOS));
    }
  私人的:
  明确会议(提高:: ASIO :: io_service对象和放大器; IOS):_socket(IOS){
    静态为size_t计数= 0;
    _id =反++;
    性病::法院LT&;< >>会话<< ID()<< 构建<<的std :: ENDL;
  }
  上市:
    无效的处理程序(常量的boost ::系统::错误_ code和; EC){
      常量的std ::字符串消息=(的boost ::格式(HTTP / 1.1 200 OK \\ r \\ nContent长度:%2%\\ r \\ n \\ r \\ nHello%1%)%ID()%( 7 +的boost :: lexical_cast的<的std ::字符串方式>(ID())长()))STR();
      如果(!EC){
        提高:: ASIO :: async_write(_socket,升压:: ASIO ::缓​​冲区(消息),提高::绑定(安培;会议:: write_handler,这一点));
      }其他{
        性病::法院LT&;< ec.message()&所述;&下;的std :: ENDL;
      }
    }
    无效write_handler(){    }
    为size_t ID()const的{
      返回_id;
    }
    提高:: ASIO ::知识产权:: TCP ::插座及放大器;插座(){
      返回_socket;
    }
    虚拟〜会话(){
      性病::法院LT&;< >>会话<< ID()<< 自毁<<的std :: ENDL;
    }
    };一流的服务器:公共的boost :: enable_shared_from_this<服务器>中私人的boost :: {不可复制
  私人的:
    提高:: ASIO :: io_service对象_ios;
    提高:: ASIO ::知识产权:: TCP ::受体_acceptor;
  上市:
    显式服务器(提高:: ASIO ::知识产权:: TCP ::端点和放大器;端点):_受体(_ios,端点){    }
    无效的start(){
      接受();
      _ios.run();
    }
    无效的accept(){
      性病::法院LT&;< 接受<<的std :: ENDL ;;
      会议::指针会话=会话::创建(_ios);
      _acceptor.async_accept(会话级>插座(),提振::绑定(安培;服务器::处理程序,为此,会议,提高:: ASIO ::占位符::错误));
    }
    无效的处理程序(会话::指针会议,常量的boost ::系统::错误_ code和; EC){
      如果(!EC){
        会话级>处理器(EC);
      }其他{
        //可能破坏会话?但如何摧毁一个共享指针?
      }
      接受();
    }
};
诠释主(){
  const的无符号整型端口= 5050;
  提高:: ASIO ::知识产权:: TCP ::端点endpoint(升压:: ASIO ::知识产权:: TCP :: V4(),端口);  Server服务器(终点);
  server.start();  返回0;
}


解决方案

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


  • 会话::处理器()的消息,所提供的基础缓冲区的 async_write() ,可能会超出范围之前 async_write()被调用。这是一个违反了API所要求的保证。考虑使的消息会话的成员变量,或使其静态成员函数中。这是从文档相关摘录:


      

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



  • 有关从的boost :: enable_shared_from_this继承对象,使用 shared_from_this()而不是通过实例时句柄的boost ::绑定这个指针。否则,它是可能的对象实例由这个可前处理程序运行删除指向。


此外,为了解决内code注释的问题服务器::处理器(),如果发生错误,则会议将曾经的处理程序返回,因为它是通过的boost :: shared_ptr的管理

删除

I am writing a Server application on boost::asio

  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.

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.

Here goes My Compilable Code

~

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(): 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:

    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:

  • 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.

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.

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

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