Socket-Programmierung: ist listen() immer blockierend?



  • Liebe Leute,

    ich stelle zum ersten Mal eine Frage im Forum und bitte um Nachsicht, wenn ich noch nicht alle Regeln kenne.

    Die Frage:
    Ist der Aufruf "listen()" immer blockierend ?

    Ich habe anhand eines Programmierbeispiels ein Konsolenprogramm geschrieben, dass einen Port abhört. Ich hatte die Funktionsweise von listen() so verstanden, dass die Programmausführung nach Aufrufen von listen() unterbrochen wird bis zur Aufnahme einer Verbindung.
    Tatsächlich läuft das Programm aber einfach durch und schließt sich, auch ohne, dass eine Verbindung auf dem Port versucht wurde (Betriebssystem: Windows).
    Wenn des Programm nach Aufruf von listen() mit system("pause") unterbrochen und mit netstat der Status der Ports abgefragt wird, erscheint der entsprechende Port mit dem Status "abhören" in der Liste, d.h. es scheint kein Fehler vorzuliegen.

    Der Code:

    [code="cpp"]
    #include <cstdlib>
    #include <iostream>
    #include <windows.h>
    #include <commctrl.h>
    #include <winsock2.h>
    using namespace std;
    
    WSADATA w;
    SOCKET s;
    
    //auf Port zugreifen
    int ListenOnPort(int PortNo)
    {
     int error = WSAStartup(0x0202,&w);
     if (error) return false;
    
     if (w.wVersion != 0x0202)
     {
      WSACleanup();
      return false;
     }
    
     SOCKADDR_IN addr; //address structure for a TCP socket
    
     addr.sin_family = AF_INET; //address family Internet
     addr.sin_port = htons (PortNo); //assign port to this socket
     addr.sin_addr.s_addr = htons(INADDR_ANY);
    
     s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //create socket
    
     if (s == INVALID_SOCKET) return false; //nicht fortfahren, wenn kein Socket erzeugt werden konnte
     if (bind(s, (LPSOCKADDR)&addr, sizeof(addr)) == SOCKET_ERROR) return false; //z.B. wenn versucht, zweimal an dieselbe Socket anzuschließen
    
     listen(s, 10); 
    }
    
    int main()
    {
      if (!ListenOnPort(50000)) cout << "Problem.\n"; 
       //Einfügen von 'system("pause");' und Abfrage mit NetStat ergibt hier, 
       //dass der Port abgehört wird; ansonsten läuft Programm einfach durch
        CloseConnection();
        closesocket(s);
        WSACleanup();
        system("pause");
    }
    

    [/code]

    Falls mir da jemand weiterhelfen kann: Vielen Dank !



  • Verwechselst du listen mit accept?



  • Bashar schrieb:

    Verwechselst du listen mit accept?

    Hallo Bashar,

    danke, Du hast Recht: listen() kommt sofort zurück, Einfügen von accept() blockiert die weitere Programmausführung.

    Die Funktion von listen() als blockierend scheint sowohl in dem Tutorial http://www.codeproject.com/Articles/13071/Programming-Windows-TCP-Sockets-in-C-for-the-Begin (Abschnitt: "Receiving Connections"), das ich gerade verwende, als auch auf der MSDN-Seite ("Note When issuing a blocking Winsock call such as listen, Winsock may need to wait for a network event before the call can complete. Winsock performs an alertable wait in this situation") falsch bzw. missverständlich beschrieben zu sein.

    Danke !



  • Dass bei Codeproject mal Müll steht, wundert mich nicht, auch die MSDN ist nicht perfekt. Aber ich auch nicht, und es kann sein, dass ich mich irre, aber ich verstehe die Manpage von listen so, dass damit nur der Socket konfiguriert wird. accept nimmt die eingehenden Verbindungen dann an -- und blockiert, falls keine anliegen.



  • Mit setsockopt kannst du ein Timeout für blockierende Sockets einstellen, mit ioctlsocket kannst du Blocking ausschalten und mit WSAAsyncSelect einen Socket asynchron schalten, sodass Events als Nachrichten an ein Window gesendet werden.



  • Und ohne WSAAsyncSelect kann man das normale select() verwenden um zu warten bis ne Verbindung "anliegt".



  • Grundsätzlich: Finger weg von Codeproject - da schreiben nur Ahnungslose. Unter 200 Artikeln findet man vielleicht mal einen Guten.


Anmelden zum Antworten