Reputation: 1705
My goal is to replace a very very simple winsock implementation, which worked perfectly, with a platform-agnostic version (for windows and linux). Using boost to provide that abstration layer, mostly since it's used elsewhere in the group so, while in Rome. It's a neat library / framework, so this is not a rant.. just not "getting" some of it, which might expose some fundamental lack of understanding.. please help me to gain such understanding.
What I had before was a very simple bing-[bang|bong] communication between a server and client. Client sent bing, server would reply with bang if all was ok, bong otherwise. Didn't need any more than that, though the capability to add on was there.
Now, going to boost, I am finding all sorts of gotchas, primarily coming down to not having been exposed to it very much yet, but I'm learning (I wish visual studio 2005's intellisense would catalog it to make it easier to navigate). I found that the read() method would block until the connection timed out, rendering inoperative, the goal of having this continuous communication. I think the socket.read_some( ) method might help me... attempting to try that.
I also am trying to refactor the connection-establishment code for use as a re-connect method too.. and that is where I am running into issues.
Consider the following:
boost::system::error_code ServiceMonitorThread::ConnectToPeer(
tcp::socket &socket,
tcp::resolver::iterator endpoint_iterator)
{
boost::system::error_code error;
int tries = 0;
for (; tries < maxTriesBeforeAbort; tries++)
{
boost::asio::connect(socket, endpoint_iterator, error);
if (error && error != boost::system::errc::success)
{
// Error connecting to service... may not be running?
string errMsg = boost::system::system_error(error).what();
cerr << errMsg << endl;
boost::this_thread::sleep_for(boost::chrono::milliseconds(200));
}
}
if (tries == maxTriesBeforeAbort)
{
return boost::system::errc::host_unreachable;
}
return error;
}
And the snippet (not yet debugged, might not be using the read_some() correctly) making use of the above:
socket.read_some(boost::asio::buffer(response), error);
switch (error)
{
case boost::system::errc::success:
break;
case boost::asio::error::eof:
// Connection was dropped, re-connect to the service.
error = ConnectToPeer(socket, endpoint_iterator);
if (error && error == boost::system::errc::host_unreachable)
{
TerminateProgram();
}
continue;
default:
// Other error while receiving from socket
string errMsg = boost::system::system_error(error).what();
cerr << errMsg << endl;
retry++;
continue;
}
Now, I get that the error_code and errc::errc_t are not the same thing... but you see the intent of what I am trying to accomplish. How do I realize the goal of the above while working within the intent of the boost framework?
Upvotes: 0
Views: 1331
Reputation: 69882
boost::system::error_code
contains both a category and an error code. It's purpose is to provide a heterogeneous type which can contain the disparate error codes of different subsystems.
Noting that system::error_code
is convertible to bool, and will only evaluate to true if there is an error:
auto bytes_read = socket.read_some(boost::asio::buffer(response), error);
if (error)
{
if (error == make_error_code(boost::asio::error::eof))
{
// Connection was dropped, re-connect to the service.
error = ConnectToPeer(socket, endpoint_iterator);
if (error && error == make_error_code(boost::system::errc::host_unreachable))
{
TerminateProgram();
}
continue;
}
else
{
cerr << error.message() << endl;
retry++;
continue;
}
}
see boost::system for description of the ADL function make_error_code
.
Upvotes: 1