Initializing boost::asio sockets after constructor

元气小坏坏 提交于 2020-01-13 05:31:12

问题


[Update:] The answer for whoever is interested, is simply wrapping the io_service member var in boost::ref (boost::ref(io_service_))

I am experimenting with the udp server example from boost asio libraries, to see if I can initialize the socket somewhere other than in the constructor. The constructor proposed in the example is the following:

class server
{
public:
  server(boost::asio::io_service& io_service, short port)
    : io_service_(io_service),
      socket_(io_service, udp::endpoint(udp::v4(), port))
  {
    socket_.async_receive_from(
        boost::asio::buffer(data_, max_length), sender_endpoint_,
        boost::bind(&server::handle_receive_from, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

I made the socket member a pointer, and also a shared pointer so that I don't have to be worried about whether it gets out of scope. "io_service_" is also a member variable and I use it to create the socket. My full code is the following:

#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

using boost::asio::ip::udp;

class server
{
public:
  server(boost::asio::io_service& io_service, short port)
    : io_service_(io_service)
      //socket_(io_service, udp::endpoint(udp::v4(), port))
  {
      initialize_socket(port);
  }

  void initialize_socket(short port)
  {

      socket_p = boost::make_shared<udp::socket>(io_service_, udp::endpoint(udp::v4(), port));
      // (...)
      socket_p->async_receive_from(
              boost::asio::buffer(data_, max_length), sender_endpoint_,
              boost::bind(&server::handle_receive_from, this,
                      boost::asio::placeholders::error,
                      boost::asio::placeholders::bytes_transferred));
  }

  void handle_receive_from(const boost::system::error_code& error,
      size_t bytes_recvd)
  {
    if (!error && bytes_recvd > 0)
    {
      std::cout << "\nReceived: ";
      std::cout.write(data_, bytes_recvd);
      std::cout << "\nSending same string back" << std::endl;
      socket_p->async_send_to(
          boost::asio::buffer(data_, bytes_recvd), sender_endpoint_,
          boost::bind(&server::handle_send_to, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }
    else
    {
      socket_p->async_receive_from(
          boost::asio::buffer(data_, max_length), sender_endpoint_,
          boost::bind(&server::handle_receive_from, this,
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));
    }
  }

  void handle_send_to(const boost::system::error_code& /*error*/,
      size_t /*bytes_sent*/)
  {
    socket_p->async_receive_from(
        boost::asio::buffer(data_, max_length), sender_endpoint_,
        boost::bind(&server::handle_receive_from, this,
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred));
  }

private:
  boost::asio::io_service& io_service_;
  boost::shared_ptr<udp::socket> socket_p;
  udp::endpoint sender_endpoint_;
  enum { max_length = 1024 };
  char data_[max_length];
};

int main(int argc, char* argv[])
{
  try
  {
    if (argc != 2)
    {
      std::cerr << "Usage: async_udp_echo_server <port>\n";
      return 1;
    }

    boost::asio::io_service io_service;

    using namespace std; // For atoi.
    server s(io_service, atoi(argv[1]));

    io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "Exception: " << e.what() << "\n";
  }

  return 0;
}

When trying to compile, I get a rather long error message from where I think the important parts are:

required from here
    /usr/local/include/boost/smart_ptr/make_shared_object.hpp:747:5: error: no matching function for call to ‘boost::asio::basic_datagram_socket<boost::asio
    ::ip::udp>::basic_datagram_socket(const boost::asio::io_service&, const boost::asio::ip::basic_endpoint<boost::asio::ip::udp>&)’
         ::new( pv ) T( a1, a2 );

(...)

   basic_datagram_socket(boost::asio::io_service& io_service,
   ^
/usr/local/include/boost/asio/basic_datagram_socket.hpp:108:3: note:   no known conversion for argument 1 from ‘const boost::asio::io_service’ to ‘boost
::asio::io_service&’

Anybody knows what was wrong with this implementation?


回答1:


make_shared<> copies its arguments (like bind or thread's c'tor). You have to wrap the io_service_ in boost::ref when passed to make_shared to ensure it gets passed as a reference:

socket_p = boost::make_shared(boost::ref(io_service_), udp::endpoint(udp::v4(), port));




回答2:


This code compiles fine on Code::Blocks IDE on windows (though I changed boost::shared_ptr to c++11 std::shared_ptr).

Probably the problem lies either within your installation of boost libraries or compiler / linker settings.

EDIT:

Compiler used is mingw_64. Boost version is 1_58_0.



来源:https://stackoverflow.com/questions/31371214/initializing-boostasio-sockets-after-constructor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!