Search code examples
boosttcpboost-asioshared-ptr

boost::asio::read throws compilation error 'read_some' is not a member of 'boost::shared_ptr<boost::asio::ip::tcp::socket>'


I am trying to build up a client to get data via a specific protocol from a server. I know that my code is not the best - but at the moment I am still experimenting with the basic functions of Boost ASIO.

I want to implement an read from TCP-Function which blocks until a specific amount of bytes have been received.

My Problem: When I call boost::asio::read or boost::asio::write i geht following error:

error C2039: 'read_some' : is not a member of boost::shared_ptr'

I am working with VS2013 Professional, Boost 1.55.00 (precompiled).

Here is my Code: ( You can find the line by the comment "//HEEERE"

boost::mutex cout_lock;

int main()
{
  // creating io_service
  boost::shared_ptr<boost::asio::io_service> io_service(new boost::asio::io_service);
  // creating work and assigning it to io_service
  boost::shared_ptr<boost::asio::io_service::work> work(new boost::asio::io_service::work(*io_service));
  // creating strand and assigning it to io_service
  boost::shared_ptr<boost::asio::io_service::strand> strand(new boost::asio::io_service::strand(*io_service));

  // creating socket
  boost::shared_ptr<boost::asio::ip::tcp::socket>   socket(new boost::asio::ip::tcp::socket(*io_service));

  try {
    // creating resolver
    boost::asio::ip::tcp::resolver resolver(*io_service);
    // creating query
    boost::asio::ip::tcp::resolver::query query(IPConfig_str, boost::lexical_cast<std::string>(IPConfig_PortNr));
    // creating iterator
    boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
    // creating  endpoint
    boost::asio::ip::tcp::endpoint endpoint = *iterator;

    // connecting synchronously
    socket->connect(endpoint);
  }
  catch(std::exception &ex) {
    cout_lock.lock();
    std::cout << "[main]:\t" << "Exception:" << ex.what() << std::endl;
    cout_lock.unlock();
  }

  // Create Query

  CommandCreator CMDCreator;
  Command sendCommand;
  CMDCreator.Create_fpga_GetSwVers(&sendCommand);
  std::cout << std::endl;
  std::cout << "SENT:" << std::endl;
  for (int i = 0; i < sendCommand.length; i++)
  {
    std::cout << std::hex << std::setw(2) << std::setfill('0') << int(sendCommand.buffer[i]) << ", ";
  }
  std::cout << std::endl;

  // Send Query
  boost::system::error_code ec;
  socket->async_send(boost::asio::buffer(sendCommand.buffer, sendCommand.length), boost::asio::transfer_all());

  Sleep(300); // sleep 100 ms (at least 85 <- not stable!)


  // Receive Answer - Header
  Command receiveCommandHeader;
  receiveCommandHeader.InitBuffer(4);

  // Async
//  socket->async_receive(boost::asio::buffer(receiveCommandHeader.buffer, receiveCommandHeader.length), 0, boost::bind(HandleRead, ec));

//HEEERE
  boost::asio::read(socket, boost::asio::buffer(receiveCommandHeader.buffer, receiveCommandHeader.length), boost::asio::transfer_all(), ec);    

  //shutting down
  socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
  socket->close(ec);

  io_service->stop();


  return 0;
}


class Command
{
  friend class CommandCreator;  // TODO: is there a better and as simple method as a friend class?

public:
  Command() : buffer(0)
  {}

  virtual ~Command()
  {
    delete[] buffer;
    buffer = 0;
  }

  void InitBuffer(int const len)
  {
    this->length = len;
    this->buffer = new uint8_t[len];
  }

  uint8_t* buffer;
  int length;
};

Actually the problem is located at this part of boost in the file read.hpp, where async_read_some is called from 'stream_'.

void operator()(const boost::system::error_code& ec,
        std::size_t bytes_transferred, int start = 0)
    {
      std::size_t n = 0;
      switch (start_ = start)
      {
        case 1:
        n = this->check_for_completion(ec, total_transferred_);
        for (;;)
        {
          stream_.async_read_some(
              boost::asio::buffer(buffer_ + total_transferred_, n),
              BOOST_ASIO_MOVE_CAST(read_op)(*this));
          return; default:
          total_transferred_ += bytes_transferred;
          if ((!ec && bytes_transferred == 0)
              || (n = this->check_for_completion(ec, total_transferred_)) == 0
              || total_transferred_ == boost::asio::buffer_size(buffer_))
            break;
        }

        handler_(ec, static_cast<const std::size_t&>(total_transferred_));
      }
    }

Solution

  • Okey, I've just found the problem.

    // creating socket
      boost::shared_ptr<boost::asio::ip::tcp::socket>   socket(new boost::asio::ip::tcp::socket(*io_service));
    

    I created the socket as a pointer but all the interfaces of read, read_some and other boost-library functions require the object. Therefore adding the dereferencing operator did it:

      boost::asio::async_read(*socket, boost::asio::buffer(receiveCommandHeader.buffer, receiveCommandHeader.length),
        boost::asio::transfer_all(), boost::bind(HandleRead, ec));