Host not found (authoritative) - c++

recently I wrote some app, that create many threads and connect to different servers as client, I used sockets for it, then I realized I can do it with boost library, so I rewrote app to boost part of connections work good and part give this error:
Host not found (authoritative)
I don't know why it happens, when I used getaddrbyhost it works perfectly but boost resolver give this error...
what can be wrong, every address is domain.
Here is part of code:
class client
{
public:
client(boost::asio::io_service& io_service,
const char* server, const char* port, const int i)
: resolver_(io_service),
socket_(io_service),
i_(i)
{
tcp::resolver::query query(tcp::v4(), boost::lexical_cast< std::string >( server ), boost::lexical_cast< std::string >( port ), boost::asio::ip::resolver_query_base::numeric_service);
resolver_.async_resolve(query,
boost::bind(&client::handle_resolve, this,
boost::asio::placeholders::error,
boost::asio::placeholders::iterator));
}
private:
void handle_resolve(const boost::system::error_code& err,
tcp::resolver::iterator endpoint_iterator)
{
if (!err)
{
boost::asio::async_connect(socket_, endpoint_iterator,
boost::bind(&client::handle_connect, this,
boost::asio::placeholders::error));
}
else
{
//here outputs error
std::cout << __FUNCTION__ << " Error: " << err.message() << "\n";
}
}
edit
totally weird yesterday I got problems with it and today it works... hmm maybe dhcp was busy or something

Most likely, the domain is one that is not resolvable by DNS but is resolvable by some other method that the host platform uses, such as an /etc/hosts style table, WINS, or some similar name resolution scheme.

Well, the answer is host I was trying to connect was outside my LAN network in another LAN network registered as tricky domain. I couldn't know it because I was testing around 20.000~ hosts stored in company database. I thought everything is running at just the one LAN network, but nope.

Related

boost asio broadcast not going out on all interfaces

If set up a program with boost asio.
Broadcasts are working fine, if only one network interface is present.
However, if there are more network interfaces each broadcast is being sent on one interface only. The interface changes randomly. As observed by wireshark.
I'd expect each broadcast to go out on every interface.
Who's wrong? Me, boost or my understanding of how to use boost. Well, I'm aware, that the latter is the most probable :).
And how can I get the expected behavior.
int myPort=5000;
boost::asio::io_context io_Context{};
boost::asio::ip::udp::socket socket{io_Context};
std::thread sendWorkerThread;
void SendWorkerStart() {
boost::asio::executor_work_guard<decltype(io_Context.get_executor())> work { io_Context.get_executor() };
io_Context.run();
}
void setupSocket() {
socket.set_option(boost::asio::socket_base::reuse_address(true));
socket.set_option(boost::asio::socket_base::broadcast(true));
boost::system::error_code ec;
socket.bind(boost::asio::ip::udp::endpoint(boost::asio::ip::address_v4::any(), myPort), ec);
sendWorkerThread = std::thread(udpSocket_c::SendWorkerStart, this);
SendWorkerStart();
}
void SendBroadcast(UdpMessage_t &&message, int size) {
boost::system::error_code ec;
std::lock_guard<std::mutex> lockGuard(sendMutex);
udp::endpoint senderEndpoint(boost::asio::ip::address_v4::broadcast(), myPort);
socket.async_send_to(boost::asio::buffer(message->data(), size), senderEndpoint,
[this](const boost::system::error_code& error,
std::size_t bytes_transferred) { /* nothing to do */} );
}
Thanks for your help.
Edit: It's now running on Windows, but needs to work also in Linux.
As suggested by Alan Birtles in the comments to the question i found an explanation here:
UDP-Broadcast on all interfaces
I solved the issue by iterating over he configured interfaces and sending the broadcast to each networks broadcast address as suggested by the linked answer.

Server and Client at same time with Boost-Asio

I am an AspNet programmer with 57 years of age. Because I was the only one who worked a little, back in the beginning, with C ++, my bosses asked me to serve a customer who needs a communication agent with very specific characteristics. It can run as a daemon on multiple platforms and be both client and server at times. I do not know enough but I have to solve the problem and found a chance in the Boost / Asio library.
I am new to Boost-Asio and reading the documentation I created a server and a TCP socket client that exchanges messages perfectly and two-way, full duplex.
I read several posts where they asked for the same things I want, but all the answers suggested full duplex as if that meant having a client and a server in the same program. And it's not. The definition of full duplex refers to the ability to write and read from the same connection and every TCP connection is full duplex by default.
I need to make two programs can accept connections initiated by the other. There will be no permanent connection between the two programs. Sometimes one of them will ask for a connection and at other times the other will make this request and both need to be listening, accepting the connection, exchanging some messages and terminating the connection until new request is made.
The server I did seems to get stuck in the process of listening to the port to see if a connection is coming in and I can not continue with the process to be able to create a socket and request a connection with the other program. I need threads but I do not know enough about them.
It'is possible?
As I said I'm new to Boost / Asio and I tried to follow some documents of threads and Coroutines. Then I put the client codes in one method and the server in another.:
int main(int argc, char* argv[])
{
try
{
boost::thread t1(&server_agent);
boost::thread t2(&client_agent);
// wait
t1.join();
t2.join();
return 0;
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
and two Coroutines:
void client_agent() {
parameters param;
param.load();
boost::asio::io_service io_service1;
tcp::resolver resolver(io_service1);
char port[5];
_itoa(param.getNrPortaServComunic(), port, 10);
auto endpoint_iterator = resolver.resolve({ param.getIPServComunicPrincipal(), port });
std::list<client> clients;
client c(io_service1, endpoint_iterator, param);
while (true)
{
BOOL enviada = FALSE;
while (true) {
if (!enviada) {
std::cout << "sending a message\n";
int nr = 110;
message msg(nr, param);
c.write(msg);
enviada = TRUE;
}
}
}
c.close();
}
void server_agent() {
parameters param;
param.load();
boost::asio::io_service io_service1;
std::list<server> servers;
tcp::endpoint endpoint(tcp::v4(), param.getNrPortaAgenteServ());
servers.emplace_back(io_service1, endpoint);
io_service1.run();
}
I used one port to client endpoint and other port to server endpoint. Is it correct? Required?
It starts looking like it's going to work. Each of the methods runs concurrently but then I get a thread allocation error at the io_service1.run (last line of the server_agent method):
boost::exception_detail::clone_impl > at memory location 0x0118C61C.
Any suggestion?
You are describing a UDP client/server application. But your implementation is bound to fail. Think of an asio server or client as always running in a single thread.
The following code is just so you get an idea. I haven't tried to compile it. Client is very similar, but may need a transmit buffer, depends on the app, obviously.
This is a shortened version, so you get the idea. In a final application you way want to add receive timeouts and the likes. The same principles hold for TCP servers, with the added async_listen call. Connected sockets can be stored in shared_ptr, and captured by the lambdas, will destroy almost magically.
Server is basically the same, except there is no constant reading going on. If running both server and client in the same process, you can rely on run() to be looping because of the server, but if not, you'd have to call run() for each connection. run() would exit at the end of the exchange.
using namespace boost::asio; // Or whichever way you like to shorten names
class Server
{
public:
Server(io_service& ios) : ios_(ios) {}
void Start()
{
// create socket
// Start listening
Read();
}
void Read()
{
rxBuffer.resize(1024)
s_.async_receive_from(
buffer(rxBuffer),
remoteEndpoint_,
[this](error_code ec, size_t n)
{
OnReceive(ec, n); // could be virtual, if done this way
});
}
void OnReceive(error_code ec, size_t n)
{
rxBuffer_.resize(n);
if (ec)
{
// error ... stops listen loop
return;
}
// grab data, put in txBuffer_
Read();
s_.async_send_to(
buffer(txBuffer_),
remoteEndpoint_,
[this, msg](error_code ec, size_t n)
{
OnTransmitDone(ec, n);
});
}
void OnTransmitDone(error_code ec, size_t n)
{
// check for error?
txBuffer_.clear();
}
protected:
io_service& ios_;
ip::udp::socket s_;
ip::udp::endpoint remoteEndpoint_; // the other's address/port
std::vector<char> rxBuffer_; // could be any data type you like
std::vector<char> txBuffer_; // idem All access is in one thread, so only
// one needed for simple ask/respond ops.
};
int main()
{
io_service ios;
Server server(ios); // could have both server and client run on same thread
// on same io service this way.
Server.Start();
ios_run();
// or std::thread ioThread([&](){ ios_.run(); });
return 0;
}

How do I convert a host name in to a boost address or endpoint?

I'm using a C++ Redis Library on top of Boost. (https://github.com/nekipelov/redisclient)
To connect, I have to give it either a single tcp endpoint:
boost::asio::ip::tcp::endpoint
Or an address + port
boost::asio::ip::address, unsigned short
Currently, I started with:
boost::asio::ip::address address = boost::asio::ip::address::from_string(someIPVariable);
and passed that along with the port, it worked fine and connected. However, I now need to do it by hostname instead of IP. If I simply put the host name in to the line above, it throws an exception as I think it expects an IP address.
I'm used to specifying connections as just ("IP OR Hostname", port) so I'm a little unsure what's required here. I checked the constructors for both to see if any could convert a host name + port to what was required, but I can't find anything.
You need to use a tcp::resolver to do name resolution (i.e. DNS lookup):
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query("example.com", "80");
boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query);
Dereferencing the iterator gives you a resolver entry that has a tcp::endpoint:
boost::asio::ip::tcp::endpoint endpoint = iter->endpoint();
Old thread but for anyone interested...
Asynchronous version:
boost::asio::io_service io_service;
boost::asio::io_service::strand io_strand(io_service);
boost::asio::ip::tcp::resolver resolver(io_service);
resolver.async_resolve({"host", "port"},
io_strand.wrap([this](const boost::system::error_code& ec,
boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
{
if (!ec)
{
std::for_each(endpoint_iterator, {}, [this](auto& it)
{
std::cout << it.endpoint().address() << std::endl;
});
}
else
{
//ec.message()?
}
}));
Note(1): we can have multiple results from the resolve function due to systems having multiple network interfaces/adapters. This is why we should iterate through the results and check "whatever" suits your needs. E.g. check if endpoint.address().is_v4();.
Note(2): don't forget to run the I/O service: io_service.run();.

Opening a boost socket with zero padding IP string

I'm using boost 1.53 and have the following code for opening a socket :
void openConnection(std::string ip, std::string port)
{
tcp::resolver resolver_( m_ioService );
tcp::resolver::query query(boost::asio::ip::tcp::v4(), ip, port);
tcp::resolver::iterator iterator = resolver_.resolve(query);
boost::shared_ptr<tcp::socket> socket_(new tcp::socket(m_ioService));
boost::asio::connect(*socket_, iterator);
m_tcpSocket = socket_;
}
If I use ip = "192.168.2.50" I'm fine but if I use "192.168.002.050" I'm failed opening a connection.
Is there any way to tune tcp::resolver::query object for such kind of strings ?
If 192.168.002.50 does work I'd say it's a failed attempt at octal decoding (that shouldn't happen).
Otherwise it seems like a limitation in boost::asio::ip::address_v::from_string. This will - no doubt - have reasonable grounds (I don't have the RFCs memorized).
You can always just manually parse, and use the constructor that takes the octets:
address_v4(address_v4::bytes_type {192,168,2,50});
http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/ip__address_v4.html

Persistent ASIO connections

I am working on a project where I need to be able to use a few persistent to talk to different servers over long periods of time. This server will have a fairly high throughput. I am having trouble figuring out a way to setup the persistent connections correctly. The best way I could think of to do this is create a persistent connection class. Ideally I would connect to the server one time, and do async_writes as information comes into me. And read information as it comes back to me. I don't think I am structuring my class correctly though.
Here is what I have built right now:
persistent_connection::persistent_connection(std::string ip, std::string port):
io_service_(), socket_(io_service_), strand_(io_service_), is_setup_(false), outbox_()
{
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(ip,port);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ip::tcp::endpoint endpoint = *iterator;
socket_.async_connect(endpoint, boost::bind(&persistent_connection::handler_connect, this, boost::asio::placeholders::error, iterator));
io_service_.poll();
}
void persistent_connection::handler_connect(const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
{
if(ec)
{
std::cout << "Couldn't connect" << ec << std::endl;
return;
}
else
{
boost::asio::socket_base::keep_alive option(true);
socket_.set_option(option);
boost::asio::async_read_until(socket_, buf_ ,"\r\n\r\n", boost::bind(&persistent_connection::handle_read_headers, this, boost::asio::placeholders::error));
}
}
void persistent_connection::write(const std::string &message)
{
write_impl(message);
//strand_.post(boost::bind(&persistent_connection::write_impl, this, message));
}
void persistent_connection::write_impl(const std::string &message)
{
outbox_.push_back(message);
if(outbox_.size() > 1)
{
return;
}
this->write_to_socket();
}
void persistent_connection::write_to_socket()
{
std::string message = "GET /"+ outbox_[0] +" HTTP/1.0\r\n";
message += "Host: 10.1.10.120\r\n";
message += "Accept: */*\r\n";
boost::asio::async_write(socket_, boost::asio::buffer(message.c_str(), message.size()), strand_.wrap(
boost::bind(&persistent_connection::handle_write, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
void persistent_connection::handle_write(const boost::system::error_code& ec, std::size_t bytes_transfered)
{
outbox_.pop_front();
if(ec)
{
std::cout << "Send error" << boost::system::system_error(ec).what() << std::endl;
}
if(!outbox_.empty())
{
this->write_to_socket();
}
boost::asio::async_read_until(socket_, buf_ ,"\r\n\r\n",boost::bind(&persistent_connection::handle_read_headers, this, boost::asio::placeholders::error));
}
The first message I will send from this seems to send out fine, the server gets it, and responds with a valid response. I see two problem unfortunately:
1) My handle_write is never called after doing the async_write command, I have no clue why.
2) The program never reads the response, I am guessing this is related to #1, since asyn_read_until is not called until that function happens.
3) I was also wondering if someone could tell me why my commented out strand_.post call would not work.
I am guessing most of this has to due with my lack of knowledge of how I should be using my io_service, so if somebody could give me any pointer that would be greatly appreciated. And if you need any additional information, I would be glad to provide some more.
Thank you
Edit call to write:
int main()
{
persistent_connection p("10.1.10.220", "80");
p.write("100");
p.write("200");
barrier b(1,30000); //Timed mutex, waits for 300 seconds.
b.wait();
}
and
void persistent_connection::handle_read_headers(const boost::system::error_code &ec)
{
std::istream is(&buf_);
std::string read_stuff;
std::getline(is,read_stuff);
std::cout << read_stuff << std::endl;
}
The behavior described is the result of the io_service_'s event loop no longer being processed.
The constructor invokes io_service::poll() which will run handlers that are ready to run and will not block waiting for work to finish, where as io_service::run() will block until all work has finished. Thus, when polling, if the other side of the connection has not written any data, then no handlers may be ready to run, and execution will return from poll().
With regards to threading, if each connection will have its own thread, and the communication is a half-duplex protocol, such as HTTP, then the application code may be simpler if it is written synchronously. On the other hand, if it each connection will have its own thread, but the code is written asynchronously, then consider handling exceptions being thrown from within the event loop. It may be worth reading Boost.Asio's
effect of exceptions thrown from handlers.
Also, persistent_connection::write_to_socket() introduces undefined behavior. When invoking boost::asio::async_write(), it is documented that the caller retains ownership of the buffer and must guarantee that the buffer remains valid until the handler is called. In this case, the message buffer is an automatic variable, whose lifespan may end before the persistent_connection::handle_write handler is invoked. One solution could be to change the lifespan of message to match that of persistent_connection by making it a member variable.