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.