28.03.2024, 10:05 UhrDeutsch | English
Hallo Gast [ Registrierung | Anmelden ]

Neues Thema eröffnen   Neue Antwort erstellen
Vorheriges Thema anzeigen Druckerfreundliche Version Einloggen, um private Nachrichten zu lesen Nächstes Thema anzeigen
Autor Nachricht
Dannyboy
Titel: Posix Threads entfernen ?  BeitragVerfasst am: 18.06.2006, 11:12 Uhr



Anmeldung: 30. Jun 2005
Beiträge: 449

Hallo Freunde der parallelen Algorithmen,
ich öffne n Threads, was wunderbar funktioniert, da ich den Rückgabewert auf 0 Prüfe. Hier:
Code:

threadmsg = pthread_create(&threads[i],
                              NULL,
                              threadSendTCPRequest, 
                              &portArray[currentPort]);
         if (threadmsg == 0)
            threadcount++;
         else ...

Hier werden alle n Threads dann wieder entfernt, was ebenfalls wunderbar funktioniert
Code:

int msg_cancel = 0, remthreads = 0;
      for (int i=0; i < threadAmount; i++) {
         if (threads[i] == 0)
            continue;
         msg_cancel = pthread_cancel(threads[i]);
         if (msg_cancel == 0){
            remthreads++;
            threads[i] = 0;               
         }
         else         
            cout <<"Thread could NOT be removed! Err.: "<<msg_cancel<<endl;            
      }
      cout<<remthreads<<"Threads were removed." <<endl;


Status der Threads gibt keine Fehlermeldung, is' also auch o.k.:
Code:
 
if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) +
      pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS , NULL) != 0)
   cout <<" unable to set thread's cancelstate/type!"<<endl;

Ich lasse die erzeugten und entfernten Threads prüfen und da diese beiden Summen identisch sind, kann ich davon ausgehen, dass stets alle erzeugten Threads auch wieder korrekt entfernt werden. Es gibt beim Entfernen der Threads keine Fehlermeldung und ich krieg' schön die 0 zurück.

Problem:
Obwohl die Threads lt. der Funktion <pthread_cancel()> alle korrekt entfernt werden, kann ich nach dem Anlegen und Löschen der Threads keine neuen Threads mehr anlegen, da das System trotz <pthread_cancel()> nicht rafft, dass die Threads freigegeben worden sind. :schock: Ich kann also maximal 382 Threads ausführen und löschen, danach ist Schluss. :schock:
Seht Euch mal den Verlauf an:
Code:

portscanner was executed ...
portscanner (C) copyright DANNYBOY 2006
***************************************

--> scanning IP 66.249.85.104 on ports 0 - 3000
--> please wait until scanning is finished ...
Amount of threads each time: 100

Checking ports 0 - 100 ...
100 threads were created ...
100 threads were removed.

Checking ports 100 - 200 ...
100 threads were created ...
100 threads were removed.

Checking ports 200 - 300 ...
100 threads were created ...
100 threads were removed.

Checking ports 300 - 400 ...
82 threads were created ...
82 threads were removed.

Checking ports 400 - 500 ...
0 threads were created ...
0 threads were removed.

Hatte statt <PTHREAD_CANCEL_ASYNCHRONOUS> auch schon <PTHREAD_CANCEL_DEFERRED> probiert, geht ebenfalls nicht. Threads werden korrekt entfernt, aber irgendwie denkt Linux, dass die entfernten Threads noch vorhanden sind und lässt mich keine neuen Threads anlegen. Hab' in den Tutorials nix weiteres gefunden. Momentan laufen die Threads nur in 'ner Schleife mit 'nem kleinen sleep(). Innerhalb der Threads kann ich sie nicht entfernen, da sie hier später eine Verbindung im Block-Modus checken sollen. Was fehlt in meinem Programm um die Threads korrekt zu entfernen?

Greetz
DANNY
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Boregard
Titel: RE: Posix Threads entfernen ?  BeitragVerfasst am: 23.06.2006, 08:15 Uhr



Anmeldung: 20. Mai 2005
Beiträge: 323
Wohnort: Niedernberg
Ich habe mal ein Testprogram gemacht, aufgrund Deiner Angaben (es war mein erstes pthreads Progtramm).

Wenn ich in einer Schleife threads anlege und beende, dann kommt irgendwann ein beim create ein Returnwert "kein Speicher mehr".
Wenn ich dann nach dem pthread cancel ein join mache geht es:
Code:
        if ((r = pthread_cancel(thread)) != 0)
        {
            printf("pthread_cancel returned %s (count: %d)\n", strerror (r), i);
            exit(1);
        }

        void *status;

        if ((r = pthread_join(thread, &status)) != 0)
            printf("pthread_join returned : %s\n", strerror(r));


Wenn amn die Mna-page zu pthread_join liest, ist das auch logisch:
Zitat:

When a joinable thread terminates, its memory resources (thread
descriptor and stack) are not deallocated until another thread performs
pthread_join on it. Therefore, pthread_join must be called once for
each joinable thread created to avoid memory leaks.


Es werden die resourcen nicht freigegeben!

Vielleicht ist das auch Dein Problem...
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Dannyboy
Titel:   BeitragVerfasst am: 27.06.2006, 03:54 Uhr



Anmeldung: 30. Jun 2005
Beiträge: 449

Hallo Boregard,
die Variante mit join funktioniert wunderbar, solange ich kein recv und kein send in den Threads aufrufe, denn sobald diese Funktionen im Thread stehen, kann und/oder will pthread_cancel den Thread nicht abbrechen. Verlegen Leider benötige ich diese beiden Funktionen unbedingt im Blocking-Modus. Gibt's da 'ne threadsichere Variante, die mir erlaubt die Threads zu schließen?

Greetz
DANNY
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Boregard
Titel:   BeitragVerfasst am: 28.06.2006, 08:23 Uhr



Anmeldung: 20. Mai 2005
Beiträge: 323
Wohnort: Niedernberg
Hi,

wenn ich das richtig verstehe, dann hast Du Aufrufe von recv und send, und während diese blockieren kann der thread nicht mit pthread_cancel abgebrochen werden?
Das schein mir auch logisch, den pthread_cancel ist nur eine Aufforderung zum beenden, siehe man-page:
Zitat:
Cancellation is the mechanism by which a thread can terminate the exe‐
cution of another thread. More precisely, a thread can send a cancella‐
tion request to another thread. Depending on its settings, the target
thread can then either ignore the request, honor it immediately, or
defer it till it reaches a cancellation point.

Wenn man weiter liest, wird auch klar, wo ein thread auf ein pthread_cancel reagiert:
Zitat:
Cancellation points are those points in the program execution where a
test for pending cancellation requests is performed and cancellation is
executed if positive. The following POSIX threads functions are cancel‐
lation points:

pthread_join(3)
pthread_cond_wait(3)
pthread_cond_timedwait(3)
pthread_testcancel(3)
sem_wait(3)
sigwait(3)

Ich denke, Du brauchst einen etwas komplizierteren Mechanismus. Ich würde mit "select" arbeiten, um ein blockieren in einer Systemfunktion vermeiden.

Gruß,
Bernhard
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Boregard
Titel:   BeitragVerfasst am: 28.06.2006, 08:32 Uhr



Anmeldung: 20. Mai 2005
Beiträge: 323
Wohnort: Niedernberg
Noch eins,

wenn man die man-page zu Ende liest:
Zitat:
BUGS
POSIX specifies that a number of system calls (basically, all system
calls that may block, such as read(2), write(2), wait(2), etc.) and
library functions that may call these system calls (e.g. fprintf(3))
are cancellation points. LinuxThreads is not yet integrated enough
with the C library to implement this, and thus none of the C library
functions is a cancellation point.

For system calls at least, there is a workaround. Cancellation requests
are transmitted to the target thread by sending it a signal. That sig‐
nal will interrupt all blocking system calls, causing them to return
immediately with the EINTR error. So, checking for cancellation during
a read system call, for instance, can be achieved as follows:


pthread_testcancel();
retcode = read(fd, buffer, length);
pthread_testcancel();

 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Dannyboy
Titel:   BeitragVerfasst am: 02.07.2006, 23:08 Uhr



Anmeldung: 30. Jun 2005
Beiträge: 449

Hi Boregard,
hab' mittlerweile verschiedene Varianten versucht das Problem zu lösen, u.a. auch mit expliziten sleeps ... das gefällt mir alles nicht. Sogar ein einfaches <cout> in 'ner Schleife reicht schon aus, damit thread_cancel() den Thread NICHT beenden kann. Daher werde ich Deinem Hinweis nachgehen und select() verwenden. Ich hatte bisher select() "nur" auf der Serverseite verwendet und hier eben bind() verwendet um quasi Port und IP mit dem Socket zu assoziieren ---> anschließend den select() (evtl. mit Timeout).

Kann ich bind() auch auf der Client-Seite verwenden oder wie verbinde ich Port und IP mit dem Socket, der anschließend bei Select() verwendet wird? select()-Tutorials zeigen immer nur die Serverseite.

So schlägt der bind() jedenfalls immer fehl, so dass ich den anschließenden select() gar nicht erst probieren brauche.
Code:

int sendTCPRequest(char* ip, int port) {
    int mySocket = INVALID;     // init. socket
    // get new socket
    mySocket = socket(AF_INET, SOCK_STREAM, 0);   // Prot. 4, TCP, standard
    if (mySocket == INVALID)
        return INVALID;
    // specify connection-partner via <sockaddr_in> struct
    sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;               // I.net Protocol v4
    serv_addr.sin_port = htons(port);            // Host to Byte order
    serv_addr.sin_addr.s_addr = inet_addr(ip);    // partner's ip address
    // bind
    int b = bind(mySocket, (sockaddr *)&serv_addr, sizeof(sockaddr_in)); //schlägt fehl
    cout<<"error in bind(): "<<endl;
...


PS:
Kannst de' ein gutes c/c++-Forum empfehlen?

Greetz
DANNY
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Boregard
Titel:   BeitragVerfasst am: 03.07.2006, 08:02 Uhr



Anmeldung: 20. Mai 2005
Beiträge: 323
Wohnort: Niedernberg
select() wird zwar oft/meist in Beispielen für TCP/IP Übertragung, und speziell dort für Server verwendet, kann aber für alle Fileoperationen verwendet werden. Und da in Unix alles ein File ist...

Ein bind ist da falsch... mit select() wartest Du doch nur darauf, das ein File was zum lesen liefert oder etwas schreiben kann. D.h. Du hast doch irgendwann ein open() gemacht. Das dabei gelieferte Handle kann im select() dann verwendet werden. Ein timeout brauchst Du natürlich, damit es nicht auch blockt.... und es muß im non-blocking-mode geöffnet sein...

Dein Beispiel müsste doch konkret so aussehen (wenns der client ist):
Code:
int sendTCPRequest(char* ip, int port) {
    int mySocket = INVALID;     // init. socket
    // get new socket
    mySocket = socket(AF_INET, SOCK_STREAM, 0);   // Prot. 4, TCP, standard
    if (mySocket == INVALID)
        return INVALID;
    // specify connection-partner via <sockaddr_in> struct
    sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;               // I.net Protocol v4
    serv_addr.sin_port = htons(port);            // Host to Byte order
    serv_addr.sin_addr.s_addr = inet_addr(ip);    // partner's ip address

    if (mySocket > 0)
    {
        /* ... and try to connect */
        if (connect (mySocket,
                     (struct sockaddr *)&serv_addr,
                     sizeof (serv_addr)            ) != 0)
        {
            cout<<"error in connect(): "<<endl;
       }
    }


Und dann kannst Du mit select() arbeiten:
Code:

    fd_set            fdsRead;
    int                 iMaxSelect;
    int                 iSelRet;
    int                 iRead;
    struct timeval      tTime;

    /* -- now loop and select -- */
    do {
        /* -- clear arrays for select -- */
        FD_ZERO (&fdsRead);

        FD_SET (iSocket, &fdsRead);

        iMaxSelect = iSocket;             /* the only one is also the maximum... */

        /* -- set max. waittime -- */
        tTime.tv_sec  = TIMEOUTSECONDS;
        tTime.tv_usec = 0;

        errno = 0;

        iSelRet = select (iMaxSelect + 1, &fdsRead, NULL, NULL, &tTime);

        if (iSelRet > 0)
        {
            /* -- we got something on socket ?? -- */
            if (FD_ISSET (iSocket, &fdsRead))
            {
                iRead = read (iSocket, szBuffer, sizeof (szBuffer));

                if (iRead <= 0)
                    break;
              ...........

            }
        }
        else if (iSelRet < 0)
        {
            if (errno != 0)
            {
                fprintf (stderr, "Error reading from select: (%d) %s\n",
                         errno, strerror (errno));
                break;
            }
        }
        else
        {
            /* just timeout */
        }

    } while (1);
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Dannyboy
Titel:   BeitragVerfasst am: 05.07.2006, 01:26 Uhr



Anmeldung: 30. Jun 2005
Beiträge: 449

Hallo Boregard,
ich bin dem Ziel dank Deiner Hilfe nun näher. So ganz checken tu' ich's noch nicht.
Wie soll select() für 4 sec. blocken können, wenn ich explizit mit fcntl() auf non-block setze?

Ich bekomme für connect() ein
Code:
operation in progress
, jedoch für alle select() ein
Code:
bad filedescriptor
. Das Ergebnis ist für offene und geschlossene Ports gleich (Zustand mit nmap getestet). Ist das nicht eher eine schreibende, als lesende Operation im select()? Hier mein Sourcecode mit Non-Blocking und select():
Code:
// connects to foreign host via tcp
bool sendTCPRequest(char* ip, int port) {   
    int mySocket = INVALID;   // init. socket
    // get new socket
    mySocket = socket(AF_INET, SOCK_STREAM, 0);   // Prot. 4, TCP, standard
    if (mySocket == INVALID){
   cout<<"socket(): "<<strerror(errno)<<endl;
   return false;         
    }
    // specify connection-partner via <sockaddr_in> struct
    sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;               // I.net Protocol v4      
    serv_addr.sin_port = htons(port);             // Host to Byte order
    serv_addr.sin_addr.s_addr = inet_addr(ip);    // partner's ip address
    // set nonblocking mode for socket
    if (fcntl(mySocket, F_SETFL, O_NONBLOCK ) != 0){
   cout<<"fcntl(): "<<strerror(errno)<<endl;
   return false;
   }
    // try to connect
cout<<"Trying to connect to IP "<<ip<<":"<<port<<endl;
    if (connect(mySocket, (sockaddr*) &serv_addr,
                     sizeof(serv_addr))!=0)
   close(mySocket);   
    cout<<"connect(): ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;
    // select() with timeout   
    struct timeval timeout;
    timeout.tv_sec = WAIT_SECONDS;
    timeout.tv_usec = 0;
    fd_set input;
    FD_ZERO(&input);
    FD_SET(mySocket, &input);   
    int retSelect = select(mySocket+1, &input, NULL, NULL, &timeout);
    if (retSelect >0)
   cout<<"open port on --> "<<port<<endl;
    else
   cout<<"select(): ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;


Greetz
DANNY
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Boregard
Titel:   BeitragVerfasst am: 05.07.2006, 13:17 Uhr



Anmeldung: 20. Mai 2005
Beiträge: 323
Wohnort: Niedernberg
Hi,

select () blockt nicht, das macht read() oder write(). select() teilt nur mit, ob man mit read() etws lesen kann (d.h. es ist etwas angekommen), oder mit write etwas schreiben kann (d.h. die Ausgabepuffer haben noch Platz), oder ob der timeout abgelaufen ist.

Was ich nicht verstehe ist:
Code:

   if (connect(mySocket, (sockaddr*) &serv_addr,
                     sizeof(serv_addr))!=0)
     close(mySocket);

d.h. wenn der connect() schief geht, machst Du den socket mit close wieder zu, ohne eine Fehlermeldung auszugeben. Das im nachfolgenden cout ausgegeben errno kann man nicht zuordnen, das kann der (Fehler-) Status von close(), von connect() oder von irgendwas vorher sein, denn: errno wird nur dann gesetzt, wenn ein Fehler passiert, es wird nicht (unbedingt) auf 0 gesetzt wenn die Funktion erfolgreich war. Außerdem sollte man errno direkt nach einem Fehler auswerten, da es jede andere Funktion wieder umsetzen kann.
Unabhängig davon frage ich mich, warum Du bei einem fehlgeschlagenen connect() zwar close() aufrufst, dann aber weitermachst - kein Wunder, daß select() einen "bad filedescriptor" liefert...

Also finde erst mal raus, woher der "operation in progress" kommt, von connect() oder vom darauffolgenden close().

Bzgl. schreibender / lesender Operation im select(): wie bereits gesagt, select() liefert Dir nur zurück, ob du lesen kannst oder ob Du schreiben kannst. Es kommt darauf an, ob du dann read() oder write() aufrufen willst. Du kannst natürlich auch auf beides gehen und dann entsprechend abfragen, dan brauchst Du halt ein fd_set für lesen und eines für schreiben...
Hast Du Dir mal die manpages durchgelesen?

Gruß,
Boregard
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Dannyboy
Titel:   BeitragVerfasst am: 05.07.2006, 15:02 Uhr



Anmeldung: 30. Jun 2005
Beiträge: 449

Hi,
das Ganze gibt 'nen Portscanner.
Ich versuche pro Thread eine TCP-Verbindung zu einem Port aufzubauen und guck' ob's klappt. Anschl. soll keine Kommunikation stattfinden, daher auch das close() in jedem Fall. Dennoch doofer Flüchtigkeitsfehler auf einen geschlossenen Socket weitere Operationen auszuführen. Die Man-Pages zu den verwendeten Funktionen hab' ich gelesen, so ganz klar ist mir manches dennoch nicht.

Mein zweiter Rechner hat nur die Ports 21 und 22 offen und wenn ich im Blocking-Modus arbeite, dann bekomme ich das korrekte Ergebnis:
Code:

checking ports 20 - 23
4 Threads were created
WAITING...
Joining all threads ...
select(): returned with 1 (192.168.1.34:23) --> Connection refused
FD_SET(): returned with 1 (192.168.1.34:23) --> Connection refused
select(): returned with 1 (192.168.1.34:22) --> Success
FD_SET(): returned with 1 (192.168.1.34:22) --> Success
select(): returned with 1 (192.168.1.34:21) --> Success
FD_SET(): returned with 1 (192.168.1.34:21) --> Success
select(): returned with 1 (192.168.1.34:20) --> Connection refused
FD_SET(): returned with 1 (192.168.1.34:20) --> Connection refused

So far, so good. Doch mit Non-Blocking und select() krieg' ich nun die selben Ergebnisse, egal ob offener oder geschlossener Port. Somit kann ich nicht unterscheiden, welche Ports offen und welche geschlossen sind. Ich brauche scheinbar den Non-Blocking Modus, da connect() u.U sonst blockieren könnte und das wäre fatal. Hier das Ergebnis im Non-Blocking-Mode:
Code:

checking ports 20 - 23
4 Threads were created
WAITING...
Joining all threads ...
select(): returned with 1 (192.168.1.34:20) --> Operation now in progress
FD_SET(): returned with 1 (192.168.1.34:20) --> Operation now in progress
select(): returned with 1 (192.168.1.34:23) --> Operation now in progress
FD_SET(): returned with 1 (192.168.1.34:23) --> Operation now in progress
select(): returned with 1 (192.168.1.34:22) --> Operation now in progress
FD_SET(): returned with 1 (192.168.1.34:22) --> Operation now in progress
select(): returned with 1 (192.168.1.34:21) --> Operation now in progress
FD_SET(): returned with 1 (192.168.1.34:21) --> Operation now in progress

Hab' die Funktion nun so geschrieben, dass man die Ergebnisse in jedem Fall angezeigt bekommt und so sieht 'se aus:
Code:

// connects to foreign host via tcp
bool sendTCPRequest(char* ip, int port) {   
    int mySocket = INVALID;   // init. socket
    // get new socket
    mySocket = socket(AF_INET, SOCK_STREAM, 0);   // Prot. 4, TCP, standard
    if (mySocket == INVALID){
   cout<<"socket(): "<<strerror(errno)<<endl;
   return false;         
    }
    // specify connection-partner via <sockaddr_in> struct
    sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;               // I.net Protocol v4      
    serv_addr.sin_port = htons(port);             // Host to Byte order
    serv_addr.sin_addr.s_addr = inet_addr(ip);    // partner's ip address
    //set nonblocking mode for socket
    fcntl(mySocket, F_SETFL, O_NONBLOCK );
    //cout<<"fcntl(): "<<strerror(errno)<<endl;   
    // try to connect
//cout<<"Trying to connect to IP "<<ip<<":"<<port<<endl;
    connect(mySocket, (sockaddr*) &serv_addr,
                     sizeof(serv_addr));
//    cout<<"connect(): ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;
    // select() with timeout   
    struct timeval timeout;
    timeout.tv_sec = WAIT_SECONDS;
    timeout.tv_usec = 0;
    fd_set input;
    FD_ZERO(&input);
    FD_SET(mySocket, &input);   
    int retSelect = select(mySocket+1, &input, NULL, NULL, &timeout);
    cout<<"select(): returned with "<<retSelect<<" ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;
    int retFD = FD_ISSET(mySocket, &input);
    cout<<"FD_ISSET(): returned with "<<retFD<<" ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;
    close(mySocket);
    return true ;

Schwere Geburt. Winken

Greetz
DANNY
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Boregard
Titel:   BeitragVerfasst am: 06.07.2006, 09:23 Uhr



Anmeldung: 20. Mai 2005
Beiträge: 323
Wohnort: Niedernberg
Hi,

das "Operation now in progress" scheint doch wohl daher zu kommen, da der Zugriff normalerweise blockieren würde, aber durch non-blocking kommt er mit dieser Meldung zurück.
Ich weiß aber nicht, ob das überhaupt funktioniert, Du willst ja mit select() nicht auf lese / schreibe, sondern auf den connect().
Vielleicht gehts mit den exceptios im select anstatt von lesen...
Trotzdem: irgendwie fehlt mir bei Deinem Programm die Schleife um select().
Du nimmst doch select(), damit es nicht blockiert, d.h. wenn Du im blocking arbeitest, dann kehrt der Aufruf zu connect() erst zurück, wenns geht oder nicht geht, d.h. es wird gewartet ("blocked") bis ein Ergebnis vorliegt. Im non-blocking kehrt er sofort zurück. Zwar sollte das select() durch den timeout warten, ABER: select() kehrt NICHT nur zurück, wenn entweder der abgefragte Descriptor oder der timeout aufgetereten sind, es kann auch durch andere Aktionen (z.B. ein Signal) mit timeout zurückkehren, OHNE daß die Zeit wirklich verstrichen ist....

Ich würde es so versuchen (Achtung: ungetestet!):
Code:

// connects to foreign host via tcp
bool sendTCPRequest(char* ip, int port) {   
    int mySocket = INVALID;   // init. socket
    // get new socket
    mySocket = socket(AF_INET, SOCK_STREAM, 0);   // Prot. 4, TCP, standard
    if (mySocket == INVALID){
        cout<<"socket(): "<<strerror(errno)<<endl;
        return false;         
    }
    // specify connection-partner via <sockaddr_in> struct
    sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;               // I.net Protocol v4     
    serv_addr.sin_port = htons(port);             // Host to Byte order
    serv_addr.sin_addr.s_addr = inet_addr(ip);    // partner's ip address
    //set nonblocking mode for socket
    fcntl(mySocket, F_SETFL, O_NONBLOCK );

    connect(mySocket, (sockaddr*) &serv_addr,
            sizeof(serv_addr));
//    cout<<"connect(): ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;
    // Now we want to see, if we can connect succesfully, as this has
    // to be done non-blocking (because of threads) we must use
    // a select() loop....
    struct timeval timeout;
    fd_set input;
    fd_set except;

    while (true)
    {
        // select() with timeout   
        timeout.tv_sec = WAIT_SECONDS;
        timeout.tv_usec = 0;
        FD_ZERO(&input);
        FD_SET(mySocket, &input);   
        FD_ZERO(&except);
        FD_SET(mySocket, &except);   

        errno = 0;

        int retSelect = select(mySocket+1, &input, NULL, NULL, &timeout);
        if (retSelect > 0)
        {
            // here we are ...
            if (FD_ISSET(mySocket, &input))
            {
                cout<<"FD_ISSET(input): returned with "
                    <<retFD<<" ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;

                // evtl. testweise den break auskommentieren, um zu sehen
                // ob "except" zieht...
                break;
            }
            else if (FD_ISSET(mySocket, &except))
            {
                cout<<"FD_ISSET(except): returned with "
                    <<retFD<<" ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;

                break;
            }
            else
            {
                cout<<"Oops: select(): returned with "<<retSelect
                    <<" ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;

                break;
            }
        }
        else if (retSelect < 0)
        {
            cout << "Error occured in select (): " << strerror(errno) << endl;
            break;
        }
        else
        {
            cout << "Timeout in select(), still waiting..." << endl;
        }
       
        int retFD =

    }
    close(mySocket);
    return true ;
}
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Boregard
Titel:   BeitragVerfasst am: 06.07.2006, 21:17 Uhr



Anmeldung: 20. Mai 2005
Beiträge: 323
Wohnort: Niedernberg
Hi,

ich habe mit etwas googlen folgendes herausgefunden:
connect() liefert bei non-blocking immer "Operation in progress" (EINPROGRESS).
Man wartet dann mit select() auf schreibende Zugriffsmöglichkeit.
Falls es überhaupt funktioniert (bekommt man mit select wirklich die errno durch das connect davor gesetzt??)
Obiger Code (dem eh except in select fehlte...) wird damit zu:
Code:

// connects to foreign host via tcp
bool sendTCPRequest(char* ip, int port) {   
    int mySocket = INVALID;   // init. socket
    // get new socket
    mySocket = socket(AF_INET, SOCK_STREAM, 0);   // Prot. 4, TCP, standard
    if (mySocket == INVALID){
        cout<<"socket(): "<<strerror(errno)<<endl;
        return false;         
    }
    // specify connection-partner via <sockaddr_in> struct
    sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;               // I.net Protocol v4     
    serv_addr.sin_port = htons(port);             // Host to Byte order
    serv_addr.sin_addr.s_addr = inet_addr(ip);    // partner's ip address
    //set nonblocking mode for socket
    fcntl(mySocket, F_SETFL, O_NONBLOCK );

    connect(mySocket, (sockaddr*) &serv_addr,
            sizeof(serv_addr));
//    cout<<"connect(): ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;
    // Now we want to see, if we can connect succesfully, as this has
    // to be done non-blocking (because of threads) we must use
    // a select() loop....
    struct timeval timeout;
    fd_set output;
    fd_set except;

    while (true)
    {
        // select() with timeout   
        timeout.tv_sec = WAIT_SECONDS;
        timeout.tv_usec = 0;
        FD_ZERO(&output);
        FD_SET(mySocket, &output);   
        FD_ZERO(&except);
        FD_SET(mySocket, &except);   

        errno = 0;

        int retSelect = select(mySocket+1, NULL, &output, &except, &timeout);
        if (retSelect > 0)
        {
            // here we are ...
            if (FD_ISSET(mySocket, &output))
            {
                cout<<"FD_ISSET(output): returned with "
                    <<retFD<<" ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;

                // evtl. testweise den break auskommentieren, um zu sehen
                // ob "except" zieht...
                break;
            }
            else if (FD_ISSET(mySocket, &except))
            {
                cout<<"FD_ISSET(except): returned with "
                    <<retFD<<" ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;

                break;
            }
            else
            {
                cout<<"Oops: select(): returned with "<<retSelect
                    <<" ("<<ip<<":"<<port<<") --> "<<strerror(errno)<<endl;

                break;
            }
        }
        else if (retSelect < 0)
        {
            cout << "Error occured in select (): " << strerror(errno) << endl;
            break;
        }
        else
        {
            cout << "Timeout in select(), still waiting..." << endl;
        }

    }
    close(mySocket);
    return true ;
}
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Boregard
Titel:   BeitragVerfasst am: 06.07.2006, 22:20 Uhr



Anmeldung: 20. Mai 2005
Beiträge: 323
Wohnort: Niedernberg
So müsste es eher gehen:
Code:
....
            if (FD_ISSET(mySocket, &output))
            {
                int soError;
                socklen_t soLen = sizeof (soError);
                if (0 != getsockopt (mySocket, SOL_SOCKET, SO_ERROR,
                                     (void *)&soError, &soLen))
                    cout<<"getsockopt error: "<<strerror(errno)<<endl;
                else
                    cout<<"FD_ISSET(output): returned with "
                        <<retFD<<" ("<<ip<<":"<<port<<") --> "<<strerror(soError)<<endl;

                break;
            }
....
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Dannyboy
Titel:   BeitragVerfasst am: 08.07.2006, 17:02 Uhr



Anmeldung: 30. Jun 2005
Beiträge: 449

Hallo Boregard,
vielen, vielen, vielen Dank für Deine Mühe und Hilfe. Du hast mir wirklich viel geholfen und viel dazu beigetragen, dass das Programm nun endlich so läuft und funktioniert, wie ich mir das gewünscht habe. Kleine Änderungen werd' ich noch am „Design“ vornehmen, doch die wesentliche Funktionalität steht. Ich habe unseren kleinen Portscanner mal mit den Ergebnissen von nmap verglichen --> Äquivalenz!!! Smilie Hier ein Testlauf beider Programme losgelassen auf www.kanotix.de

nmap (www.kanotix.de):
Code:

PORT     STATE SERVICE
21/tcp   open  ftp
22/tcp   open  ssh
25/tcp   open  smtp
53/tcp   open  domain
80/tcp   open  http
106/tcp  open  pop3pw
110/tcp  open  pop3
143/tcp  open  imap
443/tcp  open  https
465/tcp  open  smtps
993/tcp  open  imaps
995/tcp  open  pop3s
3306/tcp open  mysql
8443/tcp open  https-alt

Unser Portscanner (www.kanotix.de):
Code:

found open port (archive.kanotix.com):21
found open port (archive.kanotix.com):22
found open port (archive.kanotix.com):25
found open port (archive.kanotix.com):53
found open port (archive.kanotix.com):80
found open port (archive.kanotix.com):106
found open port (archive.kanotix.com):110
found open port (archive.kanotix.com):143
found open port (archive.kanotix.com):443
found open port (archive.kanotix.com):465
found open port (archive.kanotix.com):993
found open port (archive.kanotix.com):995
found open port (archive.kanotix.com):3306
found open port (archive.kanotix.com):8443
found open port (archive.kanotix.com):8880

Interessanterweise zeigt unser Portscanner sogar einen offenen Port mehr an (8880) als nmap.

Ich habe alle nun unnötigen Dinge (u.a. auch die Schleife) wie niemals eintretende Bedingungen und dergleichen entfernt. Folgendermaßen sieht die fertige Funktion nun aus:
Code:

// connects to foreign host via tcp and returns true if possible
bool scanPort(char* ip, int port) {   
    int mySocket = INVALID;   // init. socket
    errno=0;
    // get new socket
    mySocket = socket(AF_INET, SOCK_STREAM, 0);   // Prot. 4, TCP, standard
    if (mySocket == INVALID){
   cout<<"socket(): "<<strerror(errno)<<endl;
   return false;         
    }
    // specify connection-partner via <sockaddr_in> struct
    sockaddr_in serv_addr;
    serv_addr.sin_family = AF_INET;               // I.net Protocol v4      
    serv_addr.sin_port = htons(port);             // Host to Byte order
    serv_addr.sin_addr.s_addr = inet_addr(ip);    // partner's ip address
    //set nonblocking mode for socket
    if (fcntl(mySocket, F_SETFL, O_NONBLOCK )!=0){
   cout<<"fcntl(): "<<strerror(errno)<<endl;
   close(mySocket);
   return false;
    }       
    // try to connect (non-blocking)
    int retCon = connect(mySocket, (sockaddr*) &serv_addr, sizeof(serv_addr));
    // select() with timeout (WAIT_SECONDS)
    struct timeval timeout;
    timeout.tv_sec = WAIT_SECONDS;
    timeout.tv_usec = 0;
    fd_set output;
    int retFD = 0;   
    FD_ZERO(&output);
    FD_SET(mySocket, &output);   
    select(mySocket+1, NULL, &output, NULL, &timeout);
    // let's see if we got something to write
    retFD = FD_ISSET(mySocket, &output);
    if (retFD < 1){ // occurs sometimes in case of <no route to host>
   close(mySocket);
   return false;   
    }
    // test socket status
    int soError=0;
    socklen_t soLen = sizeof (soError);
    if ( getsockopt (mySocket, SOL_SOCKET, SO_ERROR,(void *)&soError, &soLen)!=0){
   cout<<"getsockopt error: "<<strerror(errno)<<endl;
   close(mySocket);
   return false;
    }
    // close socket because we don't want to communicate any more
    close(mySocket);
    // connection o.k. if no soError was set
    return (soError == 0);
}

Danke nochmals für alles. Sehr glücklich Sehr glücklich Sehr glücklich

Greetz
DANNYBOY
 
 Benutzer-Profile anzeigen Private Nachricht senden  
Antworten mit Zitat Nach oben
Beiträge vom vorherigen Thema anzeigen:     
Gehe zu:  
Alle Zeiten sind GMT + 1 Stunde
Neues Thema eröffnen   Neue Antwort erstellen
Vorheriges Thema anzeigen Druckerfreundliche Version Einloggen, um private Nachrichten zu lesen Nächstes Thema anzeigen
PNphpBB2 © 2003-2007 
 
Deutsch | English
Logos and trademarks are the property of their respective owners, comments are property of their posters, the rest is © 2004 - 2006 by Jörg Schirottke (Kano).
Consult Impressum and Legal Terms for details. Kanotix is Free Software released under the GNU/GPL license.
This CMS is powered by PostNuke, all themes used at this site are released under the GNU/GPL license. designed and hosted by w3you. Our web server is running on Kanotix64-2006.