Archiv verlassen und diese Seite im Standarddesign anzeigen : Timeout bei send/recv
xDannyOx
23.02.2005, 14:14
Hi,
ich hab folgendes Problem. Ich mache eine Socket-Connection zu einem Server auf und sende ihm mit Hilfe von send(...) einen Befehl! Nun sendet mir der Server eine Antwort, die ich mit Hilfe von recv(...) empfange. Das klappt in den meisten Fällen. Nun hatte ich aber bei einem Server das Problem, das ich ihm einen Befehl gesendet habe und mit recv(...) die Antwort empfangen wollte. Da aber anscheinend keine Antwort kam blieb mein Programm im recv(...)-Aufruf hängen und mein Programm stand.
Gibt es die Möglichkeit einen Timeout einzubauen, damit der recv(...)-Aufruf nach ein paar Sekunden abgebrochen wird und mein Programm weiterläuft?
Gruß Danny
butterkeks
23.02.2005, 14:43
Das müsste mit select() gehen.
Ein Tutorial kann das viel besser erklären als ich; Frag mal google nach der select() funktion udn schau dir die Manpage an.
Wie man das unter Winsock lösen würde weiß ich allerdings net, weil ich keine Ahnung hab, ob es eine select() Funktion unter Windows gibt, oder zumindest was vergleichbares.
In diesem Falle müssteste das leider in einen 2. Thread verlagern, schätze ich
Es heißt 'vbselect' um eine Verwechslung mit 'Select Case' zu vermeiden.
Im übrigen ist es sinnig, diese Funktion prinzipiell mit einem Timer zu nutzen um die Sockets auf ihren Status zu prüfen. Du kannst damit das Socket auf read-, write- und errormode überprüfen um festzustellen ob Daten im Puffer geschrieben oder gelesen werden sollen bzw. ob das Socket einen Fehler hat (letzteres z.B. bei Disconnected).
//edit : von daher ist es die richtige Methode um zu prüfen, ob eines Deiner Sockets gerade Daten empfängt oder die Verbindung getrennt wurde.
butterkeks
24.02.2005, 13:48
Im übrigen ist es sinnig, diese Funktion prinzipiell mit einem Timer zu nutzen um die Sockets auf ihren Status zu prüfen. Du kannst damit das Socket auf read-, write- und errormode überprüfen um festzustellen ob Daten im Puffer geschrieben oder gelesen werden sollen bzw. ob das Socket einen Fehler hat (letzteres z.B. bei Disconnected).
Das was du da vorschlägst nennt man "Polling" und das resultiert i.d.R. in einer schlechteren Performance als select() oder ein blockierender recv() Aufruf in einem anderen Thread.
Um einen Thread nach einiger Zeit abzuschießen kann man jedoch einen Timer nehmen, denke ich
Felix Kaiser
24.02.2005, 17:29
Die Winsock Funktion select kann exakt genauso verwendet werden, wie die gleichnamige POSIX Funktion. Einziger Unterschied ist, dass der erste Parameter, der Wert des höchsten Sockets, ignoriert wird. Windows arbeitet mit Handles, POSIX mit Deskriptoren, die vergleichbar sind mit einem Index, der bei 0 zu zählen beginnt.
Die Performance leidet nicht wahnsinnig darunter, ich denke das kann man vertreten. Im übrigen wüsste ich außer vbselect() nur noch die Möglichkeit WSAAsyncSelect() bei der man auswählen kann, auf welche Ereignisse das Socket reagieren soll und an welches Window dann welche Message gesendet wird.
Wo ist eigentlich der Themenstarter ? Irgendwie fachsimpeln wir und der gute Mann meldet sich gar nicht mehr... :)
Felix Kaiser
25.02.2005, 15:21
Es gibt keine Winsock Funktion vbselect. Um das mal noch zu erwähnen.
Sorry, ich hab in meinem Code die Socket-Funktion 'select()' in 'vbselect()' nach einer Empfehlung von einem Tut umbenannt um eben Schwierigkeiten mit dem 'Select Case'-Statement zu vermeiden.
hi hab auch ne frage bezueglich timeouts und wollte nicht extra nen neuen thread eroeffnen und zwar geht es bei mir um die connect() function...der code sieht folgendermasen aus:
111 for (i=0; i < count; i++)
112 {
113 // socket descriptoren beziehen
114 if((sock->sockfd[i] = socket(AF_INET, SOCK_STREAM, 0)) == -1)
115 {
116 fprintf(stdout, "error at socket descriptor: %d\n",sock->sockfd[i]);
117 exit(1);
118 }
119
120 // lose "address already in use" error
121 if (setsockopt(sock->sockfd[i], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
122 {
123 fprintf(stdout, "error with setsockopt at socket descriptor: %d\n", sock->sockfd[i]);
124 exit(1);
125 }
126
127 // die '\n' wegkuerzen
128 chomp(ip_ptr->wert[i]);
129
130 // ip zum connecten einlesen
131 their_addr[i].sin_family = AF_INET;
132 their_addr[i].sin_port = htons(PORT);
133 inet_aton(ip_ptr->wert[i], &(their_addr[i].sin_addr));
134 memset(&(their_addr[i].sin_zero), '\0', 8);
135
136 // connect to the daemons
137 if (connect(sock->sockfd[i], (struct sockaddr *)&their_addr[i], sizeof(struct sockaddr)) == -1)
138 {
139 perror("connect");
140 fprintf(stdout, "error connecting socket descriptor: %d\n", sock->sockfd[i]);
141 }
142 }
das programm sieht so aus das ich eine liste mit IPs einlese und mich bei wunsch zu diesen connecte das problem ist wenn eine dieser ips nicht vorhanden ist (z.B. daemon down, oder server down) dann wartet der einige minuten bevor er mir die meldung "error connecting socket descriptor ..." ausgibt.
hat einer von euch vielleicht eine idee wie man das loesen koennte?
danke und Gruessle TDO
butterkeks
01.03.2005, 18:12
Ich schätze, du wirst dein connect() in einen Thread packen und diesen Thread halt nach einem selbst festgelegten Timeout abschießen müssen
Ich schätze, du wirst dein connect() in einen Thread packen und diesen Thread halt nach einem selbst festgelegten Timeout abschießen müssen
ok ... und nun fuer die dummen .. was ist nen thread, wie kann ich das bewerkstlligen ... oder haste was wo ich das nachlesen kann?
Grüssle TDO
butterkeks
02.03.2005, 15:03
welches Betriebsystem?
welches Betriebsystem?
sry vergessen das dazuzuschreiben
Linux gentoo
compiler: gcc
grüssle TDO
butterkeks
02.03.2005, 16:38
http://www.mario-konrad.ch/index.php?page=30100
hab ich mal auf die Schnelle gefunden; Wenn du was besseres suchst, kannste ja mal googeln
http://www.mario-konrad.ch/index.php?page=30100
hab ich mal auf die Schnelle gefunden; Wenn du was besseres suchst, kannste ja mal googeln
habe nun threads eingebaut ... tut auch soweit ... nur besteht noch das alte problem ... mit dem blockierenden connect() is ja auch verstaendlich.
hier noch eine frage ... wie kann ich diesen timeout realisieren ... ich meine wie ich einen bestimmten thread abschiessen kann weiss ich ... nur faellt mir nicht ein wie man abfragen koennte ob der thread bzw. die connect function blockiert. Um die richtige abschiessen zu koennen. :-/
hoffe jemand hat da mal nen rat
gruessle TDO
Felix Kaiser
04.03.2005, 13:10
Vergesst den Müll mit dem Thread. Setz den Socket auf Non-Blocking, ruf den connect() auf und dann kannst mit mit select() warten bis innerhalb eines Zeitraumes entweder ein Write-Event oder ein Error-Event auftritt. Non-Blocking ein-/ausstellen kannst du mit der Standard LIBC Funktion fcntl() machen.
hi,
ich hab gelesen das es nicht empfehlenswert ist sockets als nicht blickierend zu erstellen da das irgendwie viel CPU leistung verbraucht oder so .... oder is das eigentlich egal?
gruessle TDO
Felix Kaiser
04.03.2005, 20:38
Man arbeitet eher selten mit blockierenden Sockets. Mehr Rechenzeit verbrauchen die auch nicht. Es kommt immer darauf an, wie deine Anwendung arbeitet. Wenn sie mit nur einer TCP-Verbindung arbeitet und sonst keine Aufgaben zu bewältigen hat, dann genügt ein blockierender Socket. In allen anderen Fälle setzt man auf nicht blockierende Sockets.
... würde mir jemand freundlicherweise erklären was der Unterschied zwischen blockierenden und nicht blockierenden Sockets ist ?
hi, nen socket ist im normalfall also per default blockierend sprich ... er "blockiert" eine zeit lang bis ein ereigniss eintritt .. sprich er wartet .. doch so lange der socket wartet ... b leibt dein komplettes programm haengen da es ja bei dem aufruf der function wie in diesem fall connect nicht weitermachen kann ehe connect nicht einen wert zurueckliefert ... das is ein "blockieren" ...
bei nicht blockierenden sockets wird sofort eine meldung zureuckgegeben ... man muss aber die ganze zeit ueberprüfen (in einer schleife) ob irgendwelche veraenderungen aufgetreten sind ... zb. ein listen() aufruf ... mit einem blockierenden socket wuerde es einfach abwarten bis eine connection reincommt also "blockieren" (das programm am weiterarbeiten hindern) ... wenn man nun einen nicht blockierenden socket an listen() uebergibt muss man in einer schleife die ganze zeit abfragen ob eine connection eingegangen ist da das listen dann die ganze zeit zueruckliefert : nein, nein, nein, nein, nein .... und irgendwann mal ja ... ich hoffe das is nun nicht zu konfus erklaert -.-
gruessle TDO
butterkeks
07.03.2005, 16:11
Es ist aber von der Performance her schlecht, wenn du es in einer SChleife machst.
Bei einer Schleife prüft dein Programm die Sockets von Hand, bei select() nimmt dir jedoch das OS die Arbeit ab und sagt dir bescheid, sobald was da ist.
Während du bei select() wartest, ist dein Prozess suspended, d.h. er verbraucht keine bis wenig CPU Cycles; Bei einer Schleife werden immer weiter Cycles verbraten.
Da das OS ja näher an der Hardware dran ist, kann es bessere Performance bieten als dein Programm es könnte.
Da Felix keine Schleife verwendet, beeinträchtigen blocking Sockets in seiner Variante jedoch nicht die Performance
Es ist aber von der Performance her schlecht, wenn du es in einer SChleife machst.
Bei einer Schleife prüft dein Programm die Sockets von Hand, bei select() nimmt dir jedoch das OS die Arbeit ab und sagt dir bescheid, sobald was da ist.
Während du bei select() wartest, ist dein Prozess suspended, d.h. er verbraucht keine bis wenig CPU Cycles; Bei einer Schleife werden immer weiter Cycles verbraten.
Da das OS ja näher an der Hardware dran ist, kann es bessere Performance bieten als dein Programm es könnte.
Da Felix keine Schleife verwendet, beeinträchtigen blocking Sockets in seiner Variante jedoch nicht die Performance
ja ... ich hab bei mir im programm auch ne select() funktion benutzt .... sollte ja nur zur veranschaulichung sein .... und da hab ich halt ne schleife gewaehlt da es irgendwie zu kompliziert waere die select() function zu erklaeren (und ich se ganz ehrlich selbst noch nciht so ganz komplett begriffen hab :mauer: )
gruessle TDO
Damit bin ich schon einen Schritt weiter, Danke für die Antworten.
vBulletin® v3.8.6, Copyright ©2000-2012, Jelsoft Enterprises Ltd.