INVALID_SOCKET
-
Hallo
ich hab hier ein kleines Problem, und zwar:ich habe einen server der folgendes macht.
void CNetzwerkClientKaSimDlg::OnTimer(UINT nIDEvent) { // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen und/oder Standard aufrufen CDialog::OnTimer(nIDEvent); if(serverSteht==true){ string verzeichnis=aktuellesVerzeichnis; ListenSocket.sortiereAuftraegeAusOrdner(verzeichnis); for(int i=0;i<30;i++){ if(clients[i]!=INVALID_SOCKET){ string auftrag=ListenSocket.gibEinenAuftrag(); auftrag=auftrag+"TYPE:07"; //auftragsenden DatenSenden(i,auftrag); } } } }also ich habe ein array der groesse 30 mit sockets. wenn sich der erste client anmeldet dann ist er im clients[0] der zweite client in clients[1] usw.
wenn jetzt aber zb. der erste client abstürzt (powerknopf) oder jemand einfach den clienten schliesst wobei bei einem schliessen dann folgende Methode aufgerufen wird
void CNetzwerkClientKaSimDlg::OnClose() { client_connect.Close(); }kriegt der server davon nichts mit, das heisst die if abfrage if(clients[i]!=INVALID_SOCKET) wobei i=0 ist zeigt nicht das der client nicht mehr da ist.
ich hätte jetzt gedacht sobald der client nicht mehr da ist, ist das socket ein INVALID_SOCKET aber anscheinend ist das nicht so.
koennt ihr mir sagen wie ich zb. erkennen kann ob der client noch da ist? bzw was ich falsch mache.
vielen dank und viele grüsse
ender
-
versuchs mal mit einem Select() vor dem senden, da tust du den client in das error und in das send set, das select wird .... eigentlich .... immer > 0 ergeben (wenn kein error dann wird send gelingen, wenn send nicht gelingen wird, wird ein fehler vorliegen) du musst nur noch prüfen ob der socket im send oder im error set ist
-
Ceos schrieb:
versuchs mal mit einem Select() vor dem senden, da tust du den client in das error und in das send set, das select wird .... eigentlich .... immer > 0 ergeben (wenn kein error dann wird send gelingen, wenn send nicht gelingen wird, wird ein fehler vorliegen) du musst nur noch prüfen ob der socket im send oder im error set ist
hm, ich hatte angst das ne antwort mit select kommt, weil ich keinen plan hab wofür das gut ist und wie man das benutzt.
könntest du mir vielleicht das in meinem code an der richtigen stelle einfügen also die select anweisung?
verstehe nicht ganz was du meinst mit da tust du den client in das error und in das send set.also kurz gesagt, verstehe ich nicht ganz die antwort zu benutzen.
-
http://msdn2.microsoft.com/en-us/library/ms740141.aspx
versuchs mal damit, wenn dir das nicht hilft, heut nachmittag hab ich mehr zeit oder wer anderes hilft dir ^^
-
also ich sehe mann kan damit sockets überprüfen?!
aber ich hab die in einem array drin, wie soll ich damit mehrere sockets überprüfen,indem ich select auf jedes einzelne socket im array anwende?oder
muss ich die vorher alle in ne andere structur packen mit der select umgehen kann?
ich habe schon andere select tutorials gesehen aber irgendwie weiss ich nicht was ich davon halten soll,die erklären aber total umständlich, also wenn du die zeit hast wären ein kleiner edit bei mir am code so hilfreich das ich dadrch vielleicht select verstehen könnte.
vielen dank nochmals
-
Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum WinAPI verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
weiter unten in der beschreibung steht wie man mit FD_SET FD_ZERO FD_ISSET die fd_set manipuliert, du addest einfach alle sockets zu sets und die, die error zeigen löschst du einfach .... einfach iss gut .... aber ich denk du wirst das schon packen ^^
achte darauf deine sets immer mit FD_ZERO zu initialisieren
-
Ceos schrieb:
weiter unten in der beschreibung steht wie man mit FD_SET FD_ZERO FD_ISSET die fd_set manipuliert, du addest einfach alle sockets zu sets und die, die error zeigen löschst du einfach .... einfach iss gut .... aber ich denk du wirst das schon packen ^^
achte darauf deine sets immer mit FD_ZERO zu initialisieren
Hallo, ich habe es jetzt versucht und mir etwas zusammengeschnippselt.
das sieht so auschar buf[256]; int rc; FD_SET fdSet; FD_ZERO(&fdSet); for(int i=0;i<MAX_CLIENTS;i++){ if(clients[i]!=INVALID_SOCKET) { FD_SET(clients[i],&fdSet); } } rc=select(0,&fdSet,NULL,NULL,NULL); if(rc==SOCKET_ERROR){ printf("Fehler: select, fehler code: %s\n",WSAGetLastError()); } for(int i=0;i<MAX_CLIENTS;i++){ if(clients[i]==INVALID_SOCKET){ continue; // ungültiger socket, d.h. kein verbunder client an dieser position im array } if(FD_ISSET(clients[i],&fdSet)){ rc=recv(clients[i],buf,256,0); // prüfen ob die verbindung geschlossen wurde oder ein fehler auftrat if(rc==0 || rc==SOCKET_ERROR){ printf("Client %d hat die Verbindung geschlossen\n",i); closesocket(clients[i]); // socket schliessen clients[i].~client(); // seinen platz wieder freigeben } } }so ersteinmal ich verwende CAsyncSocket
vielleicht kann ich hier gar nicht select benutzen.
select funktioniert nämlich nicht, wenn ich debugge
hängt er bei diesem befehl --> rc=select(0,&fdSet,NULL,NULL,NULL);
und weiter gehts nicht, ohne fehlermeldung.muss ich AsyncSelect weil ich CAsyncSocket verwende benutzen?
ausserdem
der letzte befehl im code clients[i].~client(); kann man das so machen?
weil clients[i]=INVALID_SOCKET; geht nicht obwohl doch eine überprüfung
if(clients[i]==INVALID_SOCKET) funktioniert.
wenn ich aber clients[i]=INVALID_SOCKET; screibe dann kann er nicht konvertieren oder so ähnlich.ich sitz schon heute wieder 3 stunden dran, bitte helft mir.
viele grüsse ender
und vielen dank nochmal
-
hängt er bei diesem befehl --> rc=select(0,&fdSet,NULL,NULL,NULL);
klar das er hängt
du hast ihm auch ausschliesslich das readset gegeben!!!
select gibt nur > 0 zurück wenn der socket NORMAL geschlossen wurdeoder irgendwelche daten anliegen.
deshalb musst du auch ein separates error und write set anlegen mit denselben sockets darin ..... ich meine das man fd_set klein schreibt wenn man den Typ verwendet
also fd_set ReadSet
mit
FD_ZERO(&ReadSet) löschst du das Setund mit
FD_SET(Socket, &ReadSet) fügst du den socket hinzuanschliessend prüfst du mt
bool FD_ISSET(Socket,&ReadSet) ob daten anliegen ein fehler anliegt oder ob der socket NICHT im schreibset liegt, was bedeutet er ist nicht sendebereit .... ansonsten übergib als TIMEOUT einfach ein mit 0 initialisiertes time_val struct und nicht einfach NULLkann sein das das etwas verworren klingt, schau mal auf die postingzeit XD
-
danke für die antwqort, ich werde es dann versuchen umzusetzen.
aber ist der server die ganze zeit geblockt? ich möchte auf dem server daten in nem ordner abfragen, alle 15 sekunden, deswegen mache ich das auch in der methode onTimer() . wenn ich einen timeout in select setze, geht der dann nach dem timeout aus dem select raus?
viele grüsse
ender
ps. und jetzt ist es noch später
-
wenn du die sockets in write error und read setzt, müsste er theoretisch nicht blocken, ansonsten, wenn du n timeout setzt, springt er nach dem timeout raus und liefert 0 zurück.
sockets im write_set liefern immer dann > 1 wenn sie sendebereit sind (praktisch immer)
wenn sie es nicht sind sind sie MEISTENS im error-modus, kannst also mit dem error set prüfen (was in dem falle auch > 1) liefert.
mit read set kannst du sowohl auf einen geschlossenen socket prüfen (select setzt diesen socket im read_set aber recv liefert unverholen 0 als rückgabe, was bedeutet socket closed)
als auch auf anliegende daten (um sie zu verarbeiten)