Sunucu hazır değilse, localhost'a bağlanırken tcp istemcisi hata atmıyor

0

Soru

Programım için tüm ağ işlevlerini bir "SimpleClient" sınıfı içinde kapsüllemeye çalıştım, bu da bu arayüzü içinde ortaya koyuyor .hpp dosyası:

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

Connect yöntemini test ederken, 8887 numaralı bağlantı noktasında localhost'ta hiçbir sunucu beklemese bile, bağlantının bir hata atmadığını fark ettim. Soketin gerçekten bağlı olup olmadığını nasıl kontrol edebilirim?

İşte uyguladığım yöntemler ve boost kullanarak davranışımı yeniden üreten küçük bir örnek.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;
}

İşte test programı:

#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

En iyi cevabı

1

Sorun benim bağlantı yöntemimin içindeydi, belli ki. Testimin içindeki bağlantıya yapılan ilk çağrı başarısız oldu, ancak soketi kapatmadı, bu nedenle ikinci çağrı herhangi bir işlem yapmadan otomatik olarak true değerini döndürdü.

TLDR: arıza durumunda, connect soketi kapatmaz ve ıs_open() öğesine yapılan herhangi bir çağrı 'true' değerini döndürür, hata durumunda sokette elle kapat() yöntemini çağırır.

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

Alternatif olarak, bir hatadan sonra soketin kullanılmaması için kontrol akışını ayarlayın. Bu daha doğal bir yaklaşım. Genellikle "is_open" i kontrol etmek zaten peşinde olduğunuz şey değildir (örneğin, uzak uç bir bağlantıyı ne zaman kapattığını algılayamaz). yine de kendi sorunuza cevap verdiğiniz için + 1!
sehe

Diğer dillerde

Bu sayfa diğer dillerde

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