【问题标题】:Boost.Asio, two readings by the same socketBoost.Asio,同一个插座的两个读数
【发布时间】:2015-05-16 17:06:14
【问题描述】:

我正在学习 Boost.Asio。我已经定义了一个具有客户端和服务器角色的类:

  • 我可以创建连接、发送请求和接收响应(客户端角色)。
  • 我可以接受请求并向这些请求发送响应(服务器角色)。
  • 我还可以创建订阅:创建连接,发送订阅请求并等待响应。如果远程端点接受请求,它将通过此​​连接定期向我发送数据。

我希望订阅后能够发出请求和接收响应,但是当我收到响应时出现问题:此时等待的套接字同时收到订阅和响应。

有时会出现死锁,有时我在等待响应时收到订阅,...

为了阅读,我使用了以下函数:

void async_receive_subscription(const socket& the_socket, read_handler_signature handler)
{
    auto self( this->shared_from_this() );

    boost::asio::async_read(
        the_socket.get(),
        boost::asio::buffer( my_buffer ),
        [this, self, the_socket, my_buffer, handler]
        ( const boost::system::error_code& error,
          std::size_t bytes_transferred )
        {
            the_socket.get().get_io_service().post(
                std::bind(
                handler,
                error,
                bytes_transferred,
                the_socket,
                my_buffer
                )
            );
            // Read the next subscription.
            async_receive_subscription(the_socket, handler);
        }
    );
}

void async_receive(const socket& the_socket, read_handler_signature handler)
{
    auto self( this->shared_from_this() );

    boost::asio::async_read(
        the_socket.get(),
        boost::asio::buffer( my_buffer ),
        [this, self, the_socket, my_buffer, handler]
        ( const boost::system::error_code& error,
          std::size_t bytes_transferred )
        {
            the_socket.get().get_io_service().post(
                std::bind(
                handler,
                error,
                bytes_transferred,
                the_socket,
                my_buffer
                )
            );
        }
    );
}

是否可以期望同一个套接字有两个响应?有什么同步机制可以避免这个问题吗?

谢谢。

【问题讨论】:

  • the_socket 的类型是什么,你是 tcp 还是 udp? (假设 tcp)。现有的答案很可能是这样
  • 是的,套接字是 TCP。它是一个指向 boost::asio::ip::tcp::socket 的共享指针。
  • 我问是因为the_socket.get().get_io_service() 不是共享指针的有效表达式
  • 是的,实际上它是boost::asio::ip::tcp::socket 的包装器。在内部定义共享指针。

标签: c++ sockets boost boost-asio


【解决方案1】:

async_read 保证只调用一次处理程序。

在调用此处理程序之前,您不得再次调用 async_read。

问题:

  1. 您是否在多个线程中运行 io_service?如果是这样,您需要通过 asio::strand 传递您的处理程序。

【讨论】:

  • 我已经更新了函数。在处理程序中,我正在调用该函数。我应该在 io_service 运行处理程序时调用该函数吗?
  • 在处理程序中,用户定义他想要使用的消息协议并应用同步机制以便使用多个线程。出于这个原因,我不想使用asio::strand
  • 坏主意。如果您想这样做,请将处理程序交给用户的线程,这样他就不会为自己或您造成同步问题
  • 好吧,我的设计不好。
  • 这个答案是正确的,我建议您使用不同的端口进行订阅。另一种方法是构建一个协议,该协议具有 SUBSCRIPTION、REQUEST、RESPONSE 等功能代码,这样您就可以根据该代码读取并以不同方式处理数据包。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-03
  • 1970-01-01
  • 2016-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多