Question

I am doing cross platform networking using Boost Asio. I have tried various connection methods and I keep getting "Element not found" asio.misc errors when try to connect to the socket on Android. I am confused because this occurs after succesfully resolving the domain name. For example, if I enter google.com for host and port 80, then the resolver will print out all 20+ google servers, but then later it won't connect saying asio.misc "Element not found"

Here is my code:

    boost::asio::io_service service;
    boost::system::error_code ec;
    boost::asio::ip::tcp::resolver resolver(service);
    boost::asio::ip::tcp::resolver::query query(host, port);
    boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query, ec);
    boost::asio::ip::tcp::resolver::iterator iterEnd;
    boost::asio::ip::tcp::endpoint ep;
    int it = 0;
    while(iter != iterEnd)
    {
        ep = *iter++;
        debug+="\nLooking at resolve with address " + ep.address().to_string();
        it++;
    }

        //Try to connect through asio
        boost::asio::ip::tcp::socket sock( service );
        //asio::connect does all the iterator work for us.
        boost::asio::connect(sock, iter, ec);

        if( ec )
        {
            return new string("Should be connected but I can't");
        }
        else
        {
            debug+= "\n     " + ec.message() + "\n     " + ec.category().name();
            return debug;
        }
Was it helpful?

Solution

The debug loop is exhausting the iterator, causing boost::asio::connect() to be invoked with an end iterator.

boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query, ec);

while(iter != iterEnd) // iterate to exhaustion
{
  ep = *iter++;
  // ...      
}

// ...
boost::asio::connect(sock, iter, ec); // use exhausted iterator

To resolve this, consider iterating over a copy of iter when building up the debug information by changing:

while(iter != iterEnd)
{
  ep = *iter++;
  // ...      
}

to:

for(tcp::resolver::iterator i = iter, end; i != end; ++i)
{
   ep = *i;
   // ...
}

Here is a complete example based roughly on the original code which demonstrates the differences:

#include <iostream>
#include <boost/asio.hpp>

void connect(const char* address, const char* port, bool exhaust)
{
  using boost::asio::ip::tcp;

  boost::asio::io_service io_service;
  tcp::resolver resolver(io_service);
  tcp::resolver::iterator iterator = resolver.resolve(
      tcp::resolver::query(address, port));

  // If flag is set, exhaust the iterator. 
  if (exhaust)
  {
    std::cout << "Exhausting iterator" << std::endl;
    for (tcp::resolver::iterator end; iterator != end; ++iterator) {}
  }
  // Otherwise, exhaust a copy of the iterator.
  else
  {
    std::cout << "Exhausting copy of iterator" << std::endl;
    for (tcp::resolver::iterator i = iterator, end; i != end; ++i) {}
  }

  tcp::socket socket(io_service);
  boost::system::error_code error;
  connect(socket, iterator, error);
  std::cout << error.category().name() << " -- " 
            << error.message() << std::endl;
}

int main()
{
  connect("google.com", "80", true);  // exhaust
  connect("google.com", "80", false); // do not exhaust
}

Which produces the following output:

Exhausting iterator
asio.misc -- Element not found
Exhausting copy of iterator
system -- Success
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top