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 Zitieren
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 Zitieren
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] Zitieren
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 Zitieren
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. Zitieren
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. Zitieren
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 Zitieren
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. Zitieren
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 Zitieren
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 Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.