Tcp client non buttare errore durante la connessione a localhost se no il server è pronto

0

Domanda

Ho provato a incapsulare tutte le funzionalità di rete per il mio programma all'interno di un "SimpleClient" di classe, che espone l'interfaccia all'interno dell' .hpp file:

class SimpleClient{
    //private
        boost::shared_ptr<boost::asio::ip::tcp::socket> signal_socket; 
    protected: 
        boost::asio::io_context my_context;
        ClientState state; //0: Ready to be used, not connected,  -1: error, 1: Connected/active, 
    public: 
       SimpleClient();
       virtual bool connect(const char* ip_address);
       virtual void disconnect();
       virtual bool sendMessage(const char* msg, int length);
       virtual int getResponse( char* msg, int length, int timeout);
       virtual int getSignalData( char* msg, int length);
       virtual ClientState getState();
};

Durante il test il metodo connect ho notato che, anche se nessun server era in attesa su localhost sulla porta 8887, la connessione non genera un errore. Come posso verificare che la presa sia collegata reale?

Qui i metodi che ho implementato e un piccolo esempio che riproduce il mio comportamento, con spinta.test:

SimpleClient::SimpleClient() : my_context() {
    signal_socket.reset();
    state = ClientState::CL_UNCON;
}

bool SimpleClient::connect(const char* ip_address) {
    boost::system::error_code ec;
    if (signal_socket != NULL && signal_socket->is_open() )
        return true;
    try {
        boost::asio::ip::tcp::endpoint signal_endpoint(boost::asio::ip::make_address(ip_address), 8887);
        signal_socket.reset(new boost::asio::ip::tcp::socket(my_context));
        signal_socket->connect(signal_endpoint, ec);
        if(ec) {
            std::cout<<ec.message()<<" "<<ec.value()<<std::endl;
            return false;
        }
    } catch(const boost::system::system_error& ex) {
        std::cout<<ex.code()<<std::endl;
        return false;
    }
    std::cout<<signal_socket<<std::endl;
    state = ClientState::CL_READY;
    return true;
}

Ecco il programma di test:

#define BOOST_AUTO_TEST_MAIN 
#define BOOST_TEST_DYN_LINK

#include "SimpleClient.hpp"

#include <boost/test/unit_test.hpp>

#include <string.h>

#define TARGET_IP "127.0.0.1"
#define BAD_IP "128.0.0.1"


BOOST_AUTO_TEST_CASE(connection_test)  {
    bool ret;
    std::cout<<"Connect to WRONG address"<<std::endl;
    SimpleClient* ut = new SimpleClient();
    BOOST_CHECK_EQUAL(ut->getState(), ClientState::CL_UNCON);
    ret = ut->connect(BAD_IP);
    BOOST_CHECK(!ret);
    std::cout<<"Connect to RIGHT address"<<std::endl;
    ret = ut->connect(TARGET_IP);
    BOOST_CHECK(ret);
    ut->disconnect();
    try{
        delete ut;
    }
    catch(const std::exception& ex) {
        std::cout<<ex.what()<<std::endl;
    }
    catch(...) {
    }
} 
boost boost-asio c++ tcp
2021-11-22 09:30:07
1

Migliore risposta

1

Il problema era all'interno del mio metodo di connessione, ovviamente. La prima chiamata per la connessione all'interno del mio test non è stato superato, ma non chiudere la presa, in modo che la seconda chiamata torna automaticamente vero senza eseguire alcuna operazione.

TLDR: in caso di guasto, la connessione non chiudere la presa, e qualsiasi chiamata a is_open() restituisce 'true', chiamata manualmente metodo close() sul socket in caso di errore.

bool SimpleClient::connect(const char* ip_address) {
    boost::system::error_code ec;
    if (signal_socket != NULL && signal_socket->is_open() )
        return true;
    try {
        boost::asio::ip::tcp::endpoint signal_endpoint(boost::asio::ip::make_address(ip_address), 8887);
        signal_socket.reset(new boost::asio::ip::tcp::socket(my_context));
        signal_socket->connect(signal_endpoint, ec);
        if(ec) {
            std::cout<<ec.message()<<" "<<ec.value()<<std::endl;
            signal_socket->close();
            signal_socket.reset();
            return false;
        }
    } catch(const boost::system::system_error& ex) {
        std::cout<<ex.code()<<std::endl;
        signal_socket->close();
        signal_socket.reset();
        return false;
    }
    std::cout<<signal_socket<<std::endl;
    state = ClientState::CL_READY;
    return true;
}
2021-11-22 14:52:56

In alternativa regolare il flusso di controllo in modo che la presa non è utilizzato a seguito di un errore. Questo è il più naturale approccio. Spesso il controllo "is_open" non è quello che stai dopo, comunque (ad esempio, non sarà in grado di rilevare quando il telecomando estremità chiusa una connessione). +1 per rispondere alla tua domanda, però!
sehe

In altre lingue

Questa pagina è in altre lingue

Русский
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................