Veröffentlicht 16. Januar 200421 j 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
16. Januar 200421 j 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
16. Januar 200421 j Autor 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]
16. Januar 200421 j Hallo, als erstes solltest Du mal das "listen" aus der Schleife herausziehen. Und wie gesagt, den socket nach erfolgreicher Kommunikation wieder schliessen. Nic
16. Januar 200421 j Autor 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.
16. Januar 200421 j Autor 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.
16. Januar 200421 j 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
16. Januar 200421 j Autor 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.
21. Januar 200421 j Autor 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
21. Januar 200421 j 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
Erstelle ein Konto oder melde dich an, um einen Kommentar zu schreiben.