8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

如何在协同程序环境中重用从 acceptor.async_accept 调用接收的 boost::asio 套接字?

Mayah 2月前

21 0

我是 Boost::Asio 的新手,遇到了 asio::ip::tcp::socket 存储问题。我从 asio::ip::tcp::acceptor.async_accept() 调用中收到一个服务器端套接字,并将其存储在已分配的

我是 Boost::Asio 的新手,遇到了 asio::ip::tcp::socket 存储问题。我从 asio::ip::tcp::acceptor.async_accept() 调用接收服务器端套接字并将其存储在分配的内存中。然后,当我启动 socket.async_send() 调用时,什么也没发生:没有操作,没有错误。如果套接字在全局内存中,一切都正常。我该怎么办?这是我的(伪)代码:

// Connecting coro
asio::awaitable<void> run_server(asio::io_context &context) // contex is globally allocated
{
        asio::ip::tcp::acceptor acceptor(context, asio::ip::tcp::endpoint{asio::ip::make_address_v4(p_joinserver->get_ip_addr()), p_joinserver->get_port()});
        while (true)
        {
// Preliminary create a soket and place it into unordered map            
auto psocket = std::make_shared<socket_t>(context);
            auto handle = std::rand();
            auto [iter, res] = p_server->connections.emplace(std::make_pair(handle,psocket)); 

            *psocket = co_await acceptor.async_accept(asio::use_awaitable); // Works OK

            asio::co_spawn(context, read_requests(handle), asio::detached);
        }
}

// Receiving and sending coro
asio::awaitable<void> read_requests(int handle)
{

    constexpr size_t buf_size = 1024;
    std::string line(buf_size, '\0');


        while (true)
        {
            auto psocket = p_server->connections.at(handle);
  
            auto n_read = co_await psocket->async_read_some(
                asio::buffer(line),
                asio::use_awaitable); // Works OK
// <> 
//..prepare sending
            auto _psocket = p_server->connections.at(handle);
            auto n_sent = co_await _psocket->async_send(
                 asio::buffer(line),
                 asio::use_awaitable); // Does nothing and throw no error 
    }
}

帖子版权声明 1、本帖标题:如何在协同程序环境中重用从 acceptor.async_accept 调用接收的 boost::asio 套接字?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Mayah在本站《sockets》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 协程的优点在于它们可以接受实际参数。我只需这样写:

    在 Coliru 上直播

    #include <boost/asio.hpp>
    #include <boost/asio/co_spawn.hpp>
    #include <iostream>
    namespace asio = boost::asio;
    using asio::ip::tcp;
    
    // Receiving and sending coro
    asio::awaitable<void> read_requests(tcp::socket s) 
    {
      constexpr size_t buf_size = 1024;
      std::string line(buf_size, '\0');
    
      while (true)
      {
        auto n_read = co_await s.async_read_some(
            asio::buffer(line),
            asio::use_awaitable); // Works OK
        // <> 
        //..prepare sending
        auto n_sent = co_await s.async_send(
              asio::buffer(line, n_read),
              asio::use_awaitable); // Does nothing and throw no error 
      }
    }
    
    // Connecting coro
    struct Config {
      std::string get_ip_addr() const { return "127.0.0.1"; }
      uint16_t get_port() const { return 8989; }
    };
    
    asio::awaitable<void> run_server(Config const* p_joinserver) 
    {
      auto executor = co_await asio::this_coro::executor;
      tcp::endpoint ep{
         asio::ip::make_address_v4(p_joinserver->get_ip_addr()),
         p_joinserver->get_port()};
    
      tcp::acceptor acceptor(executor, ep);
      while (true) {
          auto socket = co_await acceptor.async_accept(asio::use_awaitable); // Works OK
          asio::co_spawn(executor, read_requests(std::move(socket)), asio::detached);
      }
    }
    
    int main() {
      Config const cfg;
      asio::io_context ioc;
      co_spawn(ioc, run_server(&cfg), asio::detached);
      ioc.run_for(std::chrono::seconds(10));
    }
    

    如果您 坚持 服务器也必须维护连接列表,我首选的机制是指向会话对象的共享指针。在这种情况下, read_requests 应该是会话对象的成员函数。

    更好的句柄将是该会话的weak_ptr,因为它不仅保证是唯一的,而且还固有地始终指向相应的会话对象实例(除非它已终止,这可以是异步的)。

    您可以在本网站上看到大量的答案,例如

    std::list<std::weak_ptr<Session> > sessions_;
    

    或者,更惯用的说法是:

    using Handle = std::weak_ptr<Session>;
    std::list<Handle> sessions_;
    

    这将允许服务器对过期的会话进行垃圾收集(例如由于网络错误/对等断开连接而关闭的会话):

    sessions_.remove_if(&Handle::expired);
    
返回
作者最近主题: