checken ob ip:port verfügbar sind



  • Hallo.

    Ich bin auf der Suche nach einer Möglichkeit, dass ich feststellen kann ob ip:port verfügbar sind.

    Dazu habe ich hier im Forum schon ein gutes Bespiel gefunden
    http://www.c-plusplus.net/forum/261037
    Danke an Radix!

    Ich kopiere das Beispiel nochmals hier herein:

    int InetClientSocket::connectTo() const
    {
        int iRet = -1;
        int res;
        int flags;
    
        // set socket non-blocking
        if( (flags = fcntl(m_fdSocket, F_GETFL, 0)) < 0 )
            exit(-1);
        flags |= O_NONBLOCK;
        if( fcntl(m_fdSocket, F_SETFL, flags) < 0 )
            exit(-1);
    
        do
        {
            errno = 0;
            res = connect(m_fdSocket, (struct sockaddr*)&m_destAddr, sizeof(struct sockaddr_in)) ;
        }
        while( EINTR == errno );
    
        if(res < 0)
        {
            if(EINPROGRESS == errno)
            {
                struct timeval timeout = m_ConnectTimeout; 
                fd_set wfds;                // write file descr set
                FD_ZERO(&wfds);             // Watch m_fdSocket 
                FD_SET(m_fdSocket, &wfds);
    
                do
                {
                    errno = 0;
                    res = select(m_fdSocket+1, NULL, &wfds, NULL, &timeout);
                }
                while( EINTR == errno );
    
                if(FD_ISSET(m_fdSocket, &wfds)) // socket selected for write // connection successful
                {
                    // hier landet man offenbar IMMER, auch wenn kein Rechner oder LISTEN-Port erreichbar ist
    
    // Socket mit "getsockopt()" pruefen! siehe "man 2 connect"
                    int so_err;
                    socklen_t lon = sizeof(so_err);
                    res = getsockopt(m_fdSocket, SOL_SOCKET, SO_ERROR, (void*)(&so_err), &lon);
    
                    if(res < 0) // error
                        exit(-1);
                    else    // check so_err
                    {
                        if(so_err == 0) // success
                            iRet = 0;
                        else
                            exit(-1);
                    }
                }
                else 
                    exit(-1);
            }
            else // (errno != EINPROGRESS) -> connect didn't work
                exit(-1);
        }
    
        // set socket blocking again
        flags &= ~O_NONBLOCK;
        if( fcntl(m_fdSocket, F_SETFL, flags) < 0 )
            cout << "error" << endl;
    
        return iRet;
    }
    

    Ich habe den Code so verändert, dass das Timeout für das select den Wert 0 besitzt.
    Eigentlich funktioniert das ganze auch ganz gut, nur bin ich mir nicht so sicher, ob es auch für jeden möglichen Fall funktioniert oder ob es auch was besseres gibt und ich (noch) nicht kenne (boost, etc.)

    DANKE für eure Hilfe
    lg Johannes



  • Ein paar Anmerkungen hätte ich.

    Erst mal sehe ich nicht, wo Du den timeout auf 0 setzt. Du setzt ihn doch auf m_ConnectTimeout.

    Ein timeout von 0 wäre auch nicht korrekt. Bei manchen Betriebssystemen ist der connect gleich erfolgreich und bei manchen tatsächlich nicht. Dort muss man dann beispielsweise mit select warten, bis der connect erfolgt ist. Ich kann mich nicht mehr recht erinnern, aber es kann sein, dass eben Linux das erste Verhalten zeigt, so dass das select mit timeout 0 kein Problem darstellt. Ich arbeite hier auch mit AIX und dort ist es anders. Der timeout von 0 würde möglicherweise den select mit timeout beenden und Du würdest in Zeile 53 beim exit landen.

    Eine andere Sache ist eben genau dieses exit. Du versuchst offensichtlich eine wiederverwendbare Client-Socket-Klasse zu schreiben. Wenn jemand es in einem größeren Programm verwenden möchte, wäre es nicht nett, wenn ein fehlgeschlagenes connect das komplette Programm beenden würde.

    Prinzipiell solltest Du Dir überlegen, ob es überhaupt sinnvoll ist, so eine Klasse selbst zu entwickeln. Es gibt da viele Implementierungen, die genau so was machen und gut getestet sind. Boost wäre ein beispiel. Oder mein cxxtools, was ich natürlich sehr empfehle 😉 .



  • DANKE für deine Antwort!

    tntnet schrieb:

    Erst mal sehe ich nicht, wo Du den timeout auf 0 setzt. Du setzt ihn doch auf m_ConnectTimeout.

    Es ist das Beispiel von Radix. Bei mir wird nun das Timeout auf 0 gesetzt.

    tntnet schrieb:

    Ein timeout von 0 wäre auch nicht korrekt. Bei manchen Betriebssystemen ist der connect gleich erfolgreich und bei manchen tatsächlich nicht. Dort muss man dann beispielsweise mit select warten, bis der connect erfolgt ist. Ich kann mich nicht mehr recht erinnern, aber es kann sein, dass eben Linux das erste Verhalten zeigt, so dass das select mit timeout 0 kein Problem darstellt. Ich arbeite hier auch mit AIX und dort ist es anders. Der timeout von 0 würde möglicherweise den select mit timeout beenden und Du würdest in Zeile 53 beim exit landen.

    Ich verwende Linux und bei meinen Tests hat es eigentlich immer funktioniert, aber das heißt natürlich noch lange nicht, ob das auch gut gelöst ist und immer funktioniert.

    laut die.net

    The timeout argument specifies the minimum interval that select() should block waiting for a file descriptor to become ready. (This interval will be rounded up to the system clock granularity, and kernel scheduling delays mean that the blocking interval may overrun by a small amount.) If both fields of the timeval structure are zero, then select() returns immediately. (This is useful for polling.) If timeout is NULL (no timeout), select() can block indefinitely.

    Ich möchte deshalb einen sehr kleinen timeout verwenden, weil ich nicht direkt in einen blockierenden Zustand kommen kann/darf/möchte.

    Gibt es in dieser Situation eigentlich einen unterschied ob ich poll oder select verwende? 😕

    tntnet schrieb:

    Eine andere Sache ist eben genau dieses exit. Du versuchst offensichtlich eine wiederverwendbare Client-Socket-Klasse zu schreiben. Wenn jemand es in einem größeren Programm verwenden möchte, wäre es nicht nett, wenn ein fehlgeschlagenes connect das komplette Programm beenden würde.

    Ev. wäre es besser gewesen ich hätte meinen (veränderten) Code gepostet. Statt dem exit mache ich ein return -1,

    tntnet schrieb:

    Prinzipiell solltest Du Dir überlegen, ob es überhaupt sinnvoll ist, so eine Klasse selbst zu entwickeln. Es gibt da viele Implementierungen, die genau so was machen und gut getestet sind. Boost wäre ein beispiel. Oder mein cxxtools, was ich natürlich sehr empfehle 😉 .

    Unter was würde ich das bei Boost finden? Wie schon erwähnt sollte es non-blocking sein.

    DANKE!!!



  • ip_checker schrieb:

    Unter was würde ich das bei Boost finden? Wie schon erwähnt sollte es non-blocking sein.

    DANKE!!!

    Bei boost gibt es Netzwerkklassen. Das weiß ich. Aber da ich meine eigenen habe, verwende ich sie nicht.

    Cxxtools ist übrigens in den meisten Repositories auch verfügbar. Bei Debian kannst Du beispielsweise das Paket libcxxtools-dev installieren. Da gibt es eine Klasse cxxtools::net::TcpSocket. Wir haben das so gelöst, dass es ein beginConnect und ein endConnect gibt. Nach beginConnect wird die Applikation über ein Signal (kein Unix-Signal) in der Eventloop benachrichtigt, wenn es nicht blockierend ein endConnect aufrufen kann um entweder eine Connection zu erhalten oder im Fehlerfall eine Exception.

    Non-blocking ist nicht wirklich trivial. Ein möglichst kurzes Timeout ist ein Zeichen, dass man es nicht richtig gemacht hat. Aber manchmal ist das auch gut genug. Man muss ja nicht immer die akademisch korrekte Lösung implementieren.

    Und nein - es macht keinen Unterschied ob man select oder poll verwendet.


Log in to reply