Guybrush Threepwood Geschrieben 16. Januar 2004 Geschrieben 16. Januar 2004 Hi, ich hab eine Serveranwendung bei der ich mir ein Socket anlege und mit diesem in einer Schleife auf einem Port auf Verbindungsanfragen warte. Nach dem eine Verbindung mit einem Client aufgebaut wurde, erhält die Anwendung einen String, verarbeitet diesen und sendet eine Antwort zurück. Im Moment schließe ich das Socket welches ich mit accept() erhalte am Ende der Schleife nicht, allerdings scheint accept() irgendwann nicht mehr zurückzukehren, was ich darauf zurückführe das ich das Socket nicht schließe und Resourcen nicht freigegeben werden. Wenn ich das Socket aber mit closesocket() am Ende der Schleife schließe, tritt kein Fehler auf, die Anwendung nimmt aber jede Anfrage 10 mal entgegen und verarbeitet diese. Hat jemand eine Idee woran das liegen könnte? Gruß Guybrush
nic_power Geschrieben 16. Januar 2004 Geschrieben 16. Januar 2004 Hallo, poste doch mal Deinen Code, das macht die Fehlersuche einfacher. Accept arbeitet nur mit Stream-Sockets und wird nur zum Aufbau der Verbindung verwendet. Es liefert einen socket zurück, dann der zum Lesen und Schreiben verwendet wird. Wenn Du jetzt bei jedem Aufruf ein accept() ausführst, gehen Dir irgendwann die Filedescriptoren aus. Das heisst, du solltest am Ende der Verbindung den Kommunikationssocket auch schliessen. Nic
Guybrush Threepwood Geschrieben 16. Januar 2004 Autor Geschrieben 16. Januar 2004 Etwas verkürzt sieht der Code so aus: WORD Version = MAKEWORD(2,2); WSADATA WsaData; if (WSAStartup(Version,&WsaData) != NULL) //fehler if (LOBYTE(WsaData.wVersion) != 2 || HIBYTE(WsaData.wVersion != 2)) //fehler g_.ServerSocket = socket(AF_INET,SOCK_STREAM,0); if (g_.ServerSocket == INVALID_SOCKET) //fehler g_.SvrAddr.sin_family = AF_INET; g_.SvrAddr.sin_addr.s_addr = INADDR_ANY; g_.SvrAddr.sin_port = htons(5001); if (bind(g_.ServerSocket,(LPSOCKADDR)&g_.SvrAddr,sizeof(sockaddr_in)) == SOCKET_ERROR) //fehler while (true) { if (listen(g_.ServerSocket,1) == SOCKET_ERROR) //fehler addr_len = sizeof(sockaddr_in); g_.ClientSocket = accept(g_.ServerSocket,(LPSOCKADDR)&CliAddr,&addr_len); if (g_.ClientSocket == INVALID_SOCKET) //fehler if ((nBytes = recv(g_.ClientSocket,szString,600,MSG_PEEK)) == SOCKET_ERROR) //fehler /*Datenverarbeitung*/ send(g_.ClientSocket,strAntwort,strlen(strAntwort),NULL); //if (closesocket(g_.ClientSocket) == SOCKET_ERROR) //fehler } ... [/PHP]
nic_power Geschrieben 16. Januar 2004 Geschrieben 16. Januar 2004 Hallo, als erstes solltest Du mal das "listen" aus der Schleife herausziehen. Und wie gesagt, den socket nach erfolgreicher Kommunikation wieder schliessen. Nic
Guybrush Threepwood Geschrieben 16. Januar 2004 Autor Geschrieben 16. Januar 2004 Ok ich mache listen jetzt vor der schleife. Aber wie gesagt, sobald ich das socket so schließe, nimmt die Anwendung jede Verbindung 10 mal entgegen und verarbeitet diese.
Guybrush Threepwood Geschrieben 16. Januar 2004 Autor Geschrieben 16. Januar 2004 Ich hab grad festgestellt, dass wenn ich am Ende der Schleife 5-6 Sekunden warte, das Problem nicht auftritt. Da ich aber nicht solange warten kann bräuchte ich ne Idee wie ich das Umgehen kann. Anscheinend braucht Windows etwas Zeit das Socket anständig zu schließen.
nic_power Geschrieben 16. Januar 2004 Geschrieben 16. Januar 2004 Hallo, es gibt generell unterschiedliche Möglichkeiten, einen Socket zu schliessen (wird über die Optionen SO_[DONT]LINGER gesteuert). Für Windows schau mal hier: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/graceful_shutdown_linger_options_and_socket_closure_2.asp Das Problem tritt wahrscheinlich dann auf, wenn der Client den Socket noch nicht geschlossen hat. Nic
Guybrush Threepwood Geschrieben 16. Januar 2004 Autor Geschrieben 16. Januar 2004 Also ich hab das Client Socket jetzt mal nach accept auf SO_DONTLINGER gesetzt (was ja bedeutet das er es nachher direkt schließen soll), aber das hat nichts gebracht.
Guybrush Threepwood Geschrieben 21. Januar 2004 Autor Geschrieben 21. Januar 2004 Konnte das Problem gerade lösen. Es lag irgendwie daran, dass ich recv() aus irgendeinem Grund MSG_PEEK als letzten Parameter übergeben habe. Hab das jetzt durch NULL ersetzt und das Socket wird geschlossen, ohne das ich SO_DONTLINGER oder so setzen muss. Gruß Guybrush
nic_power Geschrieben 21. Januar 2004 Geschrieben 21. Januar 2004 Hallo, Original geschrieben von Guybrush Threepwood Es lag irgendwie daran, dass ich recv() aus irgendeinem Grund MSG_PEEK als letzten Parameter übergeben habe. "Irgendwie" ist nett formuliert Die Option "MSG_PEEK" führt dazu, dass die Daten zwar in dem recv()-Aufruf zurückgeliefert, jedoch nicht aus der Empfangqueue entfernt werden. Beim nächsten Aufruf werden die Daten nochmals zurück geliefert. Nic
Empfohlene Beiträge
Erstelle ein Benutzerkonto oder melde Dich an, um zu kommentieren
Du musst ein Benutzerkonto haben, um einen Kommentar verfassen zu können
Benutzerkonto erstellen
Neues Benutzerkonto für unsere Community erstellen. Es ist einfach!
Neues Benutzerkonto erstellenAnmelden
Du hast bereits ein Benutzerkonto? Melde Dich hier an.
Jetzt anmelden