Tcp cliente no tirar error al conectar a localhost, si no hay ningún servidor listo

0

Pregunta

Traté de encapsular todas las redes funcionalidades para mi programa dentro de un "SimpleClient" de la clase, que expone esta interfaz dentro de la .ch archivo:

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();
};

Mientras se prueba el método connect me di cuenta de que incluso si no hay ningún servidor estaba esperando en localhost en el puerto 8887, la conexión no se producirá un error. ¿Cómo puedo verificar que el conector está conectado real?

Aquí los métodos que he implementado y un pequeño ejemplo que reproduce mi comportamiento, mediante el impulso.prueba:

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;
}

Aquí está el programa de prueba:

#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

Mejor respuesta

1

El problema estaba dentro de mi método de conexión, obviamente. La primera llamada a connect dentro de mi error en la prueba, pero no se cierra el socket, por lo que la segunda llamada automáticamente devuelve verdadero sin realizar ninguna operación.

TLDR: en caso de fracaso, conecte no cierra el socket, y cualquier llamada a is_open() devuelve 'true', llamada manualmente método close() en el zócalo en caso de error.

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

Alternativamente ajustar el flujo de control de modo que el zócalo no se utiliza después de un error. Este es el enfoque más natural. A menudo la comprobación de "is_open" no es lo que está después de todos modos (por ejemplo, no será capaz de detectar si el extremo remoto cierra la conexión). +1 para contestar a su propia pregunta, aunque!
sehe

En otros idiomas

Esta página está en otros idiomas

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