Commit 9915996b authored by Pavel Vainerman's avatar Pavel Vainerman

(TCPCheck): переписал на использование future (async)

parent 8fad8103
...@@ -42,33 +42,19 @@ namespace uniset ...@@ -42,33 +42,19 @@ namespace uniset
* Для проверки идёт попытка открыть соединение, но данные не посылаются, а соединение сразу закрывается. * Для проверки идёт попытка открыть соединение, но данные не посылаются, а соединение сразу закрывается.
* \note Нужно быть уверенным, что сервис не зависнет от таких попыток "соединений" * \note Нужно быть уверенным, что сервис не зависнет от таких попыток "соединений"
*/ */
bool check( const std::string& _ip, int _port, timeout_t tout ); static bool check( const std::string& _ip, int _port, timeout_t tout ) noexcept;
/*! \param iaddr - 'ip:port' */ /*! \param iaddr - 'ip:port' */
bool check( const std::string& iaddr, timeout_t tout ); static bool check( const std::string& iaddr, timeout_t tout ) noexcept;
/*! Проверка связи с узлом командой ping /*! Проверка связи с узлом командой ping
* \note Вызывается через system()! Это может быть опасно с точки зрения безопасности.. * \note Вызывается через system()! Это может быть опасно с точки зрения безопасности..
* \todo Возможно стоит написать свою реализацию ping * \todo Возможно стоит написать свою реализацию ping
*/ */
bool ping(const std::string& _ip, timeout_t tout = 1000, const std::string& ping_argc = "-c 1 -w 0.1 -q -n" ); static bool ping( const std::string& _ip, timeout_t tout = 1000, const std::string& ping_argc = "-c 1 -w 0.1 -q -n" ) noexcept;
protected: protected:
void check_thread();
void ping_thread();
std::condition_variable thr_event;
std::mutex thr_mutex;
std::atomic_bool thr_finished = { false };
std::atomic_bool result = {false};
std::string ip = {""};
int port = {0};
int tout_msec;
std::string ping_args = {"-c 1 -w 0.1 -q -n"};
}; };
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
} // end of uniset namespace } // end of uniset namespace
......
...@@ -14,11 +14,13 @@ ...@@ -14,11 +14,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#include <functional>
#include <sstream> #include <sstream>
#include <cstdlib> #include <cstdlib>
#include <iostream>
#include <future>
#include <thread>
#include <chrono>
#include "UniSetTypes.h" #include "UniSetTypes.h"
#include "ThreadCreator.h"
#include "TCPCheck.h" #include "TCPCheck.h"
#include "UTCPStream.h" #include "UTCPStream.h"
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -27,8 +29,7 @@ using namespace std; ...@@ -27,8 +29,7 @@ using namespace std;
namespace uniset namespace uniset
{ {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
TCPCheck::TCPCheck() noexcept: TCPCheck::TCPCheck() noexcept
tout_msec(0)
{ {
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -37,7 +38,7 @@ namespace uniset ...@@ -37,7 +38,7 @@ namespace uniset
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
bool TCPCheck::check( const std::string& _iaddr, timeout_t tout ) bool TCPCheck::check( const std::string& _iaddr, timeout_t tout ) noexcept
{ {
auto v = uniset::explode_str(_iaddr, ':'); auto v = uniset::explode_str(_iaddr, ':');
...@@ -47,100 +48,77 @@ namespace uniset ...@@ -47,100 +48,77 @@ namespace uniset
return check( v[0], uniset::uni_atoi(v[1]), tout ); return check( v[0], uniset::uni_atoi(v[1]), tout );
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
template<typename T> bool TCPCheck::check( const std::string& ip, int port, timeout_t tout_msec ) noexcept
class TGuard
{ {
public: try
{
TGuard( T* m, typename ThreadCreator<T>::Action a ): std::future<bool> future = std::async(std::launch::async, [=]()
t(m, a)
{ {
t.start(); // Сама проверка...
std::this_thread::sleep_for(std::chrono::milliseconds(10)); bool result = false;
} try
{
~TGuard() UTCPStream t;
t.create(ip, port, tout_msec);
// если удалось создать соединение, значит OK
result = t.isConnected();
t.disconnect();
}
catch( ... ) {}
return result;
});
std::future_status status;
do
{ {
if( t.isRunning() ) status = future.wait_for(std::chrono::milliseconds(tout_msec));
t.stop(); if( status == std::future_status::timeout )
return false;
t.join();
} }
while( status != std::future_status::ready );
protected: return future.get();
ThreadCreator<T> t; }
}; catch( std::exception& ex )
// -----------------------------------------------------------------------------
bool TCPCheck::check( const std::string& _ip, int _port, timeout_t tout )
{
ip = _ip;
port = _port;
tout_msec = tout;
thr_finished = false;
result = false;
TGuard<TCPCheck> t(this, &TCPCheck::check_thread);
std::unique_lock<std::mutex> lock(thr_mutex);
thr_event.wait_for(lock, std::chrono::milliseconds(tout), [ = ]()
{ {
return ( thr_finished == true );
} );
return result; }
return false;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void TCPCheck::check_thread() bool TCPCheck::ping( const std::string& ip, timeout_t tout_msec, const std::string& ping_args ) noexcept
{ {
thr_finished = false;
result = false;
try try
{ {
UTCPStream t; std::future<bool> future = std::async(std::launch::async, [=]()
t.create(ip, port, tout_msec); {
t.setKeepAliveParams( (tout_msec > 1000 ? tout_msec / 1000 : 1) ); // Сама проверка...
result = true; ostringstream cmd;
t.disconnect(); cmd << "ping " << ping_args << " " << ip << " 2>/dev/null 1>/dev/null";
}
catch( ... ) {}
thr_finished = true;
}
// -----------------------------------------------------------------------------
bool TCPCheck::ping( const std::string& _ip, timeout_t tout, const std::string& _ping_args )
{
ip = _ip;
tout_msec = tout;
ping_args = _ping_args;
thr_finished = false;
result = false;
int ret = system(cmd.str().c_str());
int res = WEXITSTATUS(ret);
return (res == 0);
});
TGuard<TCPCheck> t(this, &TCPCheck::ping_thread); std::future_status status;
do
{
status = future.wait_for(std::chrono::milliseconds(tout_msec));
if( status == std::future_status::timeout )
return false;
}
while( status != std::future_status::ready );
std::unique_lock<std::mutex> lock(thr_mutex); return future.get();
thr_event.wait_for(lock, std::chrono::milliseconds(tout), [ = ]() }
catch( std::exception& ex )
{ {
return ( thr_finished == true );
} );
return result; }
}
// -----------------------------------------------------------------------------
void TCPCheck::ping_thread()
{
thr_finished = false;
result = false;
ostringstream cmd;
cmd << "ping " << ping_args << " " << ip << " 2>/dev/null 1>/dev/null";
int ret = system(cmd.str().c_str());
int res = WEXITSTATUS(ret);
result = (res == 0); return false;
thr_finished = true;
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
} // end of namespace uniset } // end of namespace uniset
...@@ -79,6 +79,8 @@ TEST_CASE("TCPCheck::ping", "[tcpcheck][tcpcheck_ping]" ) ...@@ -79,6 +79,8 @@ TEST_CASE("TCPCheck::ping", "[tcpcheck][tcpcheck_ping]" )
msleep(200); msleep(200);
REQUIRE( t.ping(host) ); REQUIRE( t.ping(host) );
REQUIRE_FALSE( t.ping("dummy_host_name") );
// 123.3. - dummy ip
REQUIRE_FALSE( t.ping("123.3.") );
} }
// -------------------------------------------------------- // --------------------------------------------------------
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment