Hallo, ich verwende die Bibliothek curl mit C++. curl: http://curl.haxx.se/libcurl/ chunked Verbindung: http://en.wikipedia.org/wiki/Chunked_transfer_encoding Das Programm läuft wie folgt ab. -Informationsabfrage von einem Server. -Empfangene Daten werden analysiert und curl wird konfiguriert. -In einem neuen Thread wird die Bibliothek curl ausgeführt. Dieser baut eine Verbindung (Session) mit dem Server aufgebaut. Anschließend erfolgt die Antwort als chunked Verbindung. Diese "blockiert" das Programm. Deswegen wird die chunked Verbindung in einem neuen Thread ausgeführt. Immer wenn Daten empfangen werden wird von curl eine "Writefunction" aufgerufen der die Daten zugeschoben werden. -Im Hauptthread erfolgt eine weitere Kommunikation mit dem Server. Dieser Teilt dem Server mit, welche Daten über die chunked Verbindung gesendet werden sollen. -Anschließend wird gewartet bis der Thread beendet wird (Unterbrechung des Datentransfers nach ca. 1,5h). -Das ganze beginnt von vorne. Zitat aus Wikipedia: "The last chunk is a zero-length chunk, with the chunk size coded as 0, but without any chunk data section." Problem: Wenn sich die Ip meines Rechners ändert, während die chunked Verbindung aktiv ist werden keine Daten mehr empfangen. Curl bekommt also nicht mit, dass die Verbindung beendet worden ist und der Thread läuft endlos weiter. Wie würdet Ihr das Problem lösen? Ich dachte darüber nach eine Zeitkontrolle einzubauen. Immer wenn Daten empfangen werden wird eine Variable gesetzt. Sobald über einen Zeitraum von n Sekunden keine Daten empfangen werden wird die Verbindung für tod erklärt und der Thread "zwangs"beendet. Dies kommt mir jedoch etwas unprofessionell vor. Habt Ihr Vorschläge, wie man das Problem geschickter lösen kann?
Ich hatte das mal (allerdings nicht mit Curl) durch das Senden von Keep-Alive-Chunks gelöst. War ne HTML-Anwendung, also konnte ich einfach jede Minute einen <!-- Kommentar --> über die Leitung jagen. Heute würd ich das zwar nicht mehr so machen, gibt ja inzwischen mit AJAX/WebSocket usw. bessere Möglichkeiten, aber funktioniert hats.
Ich verstehe nicht so ganz was das mit meinem Problem zu tun hat. Mein Problem ist ja, dass curl so lange wartet, bis eine Nachricht kommt. Aber die kommt nicht.
A. R. schrieb: > Wenn sich die Ip meines Rechners ändert, während die chunked Verbindung > aktiv ist werden keine Daten mehr empfangen Wie das? Sowas ist nun wirklich nicht vorgesehen, normalerweise sollte dann die Verbindung abbrechen. A. R. schrieb: > Ich dachte darüber nach eine Zeitkontrolle einzubauen. > Dies kommt mir jedoch etwas unprofessionell vor. Wieso? Das ist bei Netzverbindungen das Mittel der Wahl. A. R. schrieb: > Im Hauptthread erfolgt eine weitere Kommunikation mit dem Server. Du könntest eine Art "nop" Kommando definieren, spätestens beim Senden sollte auffallen falls die Gegenstelle nicht verfügbar ist.
>A. R. schrieb: >> Wenn sich die Ip meines Rechners ändert, während die chunked Verbindung >> aktiv ist werden keine Daten mehr empfangen >Wie das? Sowas ist nun wirklich nicht vorgesehen, normalerweise sollte >dann die Verbindung abbrechen. Eben genau das passiert nicht. Das ist mein Problem. Der Thread in dem die chunked Verbindung abläuft wird nicht beendet. Es kommt auch keine Fehlermeldung und nichts. Curl wartet einfach auf eine Antwort und es kommt nichts. Würde curl mit ner Fehlermeldung abbrechen wäre alles Super. Im Endeffekt starte ich eine Funktion und diese wird nie beendet. >A. R. schrieb: >> Ich dachte darüber nach eine Zeitkontrolle einzubauen. >> Dies kommt mir jedoch etwas unprofessionell vor. >Wieso? Das ist bei Netzverbindungen das Mittel der Wahl. Ja das wird bei Netzverbindungen öfterns gemacht. Deswegen frage ich ob das so in Ordnung ist oder ob es bessere Möglichkeiten gibt. Ich finde es etwas unprefessionell, da bei Zeitabfragen das debuggen extrem verschwert wird. Ich weiß auch nicht, wie ich die curl Verbindung abbrechen soll. Ich verwende Boost::Thread für Multithreads. Hierbei gibt es keinen close Befehl der den Thread zerstört. Zumindest ist mir keine bekannt. Curl kann ich auch nicht so ohne weiteres abbrechen. Ich kann es pausieren mehr auch nicht.
A. R. schrieb: > Ich weiß auch nicht, wie ich die curl Verbindung abbrechen soll. > Ich verwende Boost::Thread für Multithreads. Hierbei gibt es keinen > close Befehl der den Thread zerstört. Zumindest ist mir keine bekannt. Ist auch besser so. Einen Thread einfach so rauszuschießen ist keine gute Idee, besonders wenn C++, Auto-variablen mit Konstruktoren, Mutexe usw. im Spiel sind. > Curl kann ich auch nicht so ohne weiteres abbrechen. Ich kann es > pausieren mehr auch nicht. Versuch mal die CURLOPT_PROGRESSFUNCTION zu setzen. Da solltest du bei jedem internen Curl-Poll/select-Schleifenlauf einen Aufruf kriegen, und kannst von dort aus komfortabel auf Timeout warten und auch die Verbindung/curl sauber beenden.
Schoneinmal vielen vielen Dank für die Information. Wenn ich das auf der Homepage von curl richtig interpretiere ist das genau das was ich suche. Damit hast du mir richtig geholfen.
1 | CURLOPT_PROGRESSFUNCTION |
2 | |
3 | Function pointer that should match the curl_progress_callback |
4 | prototype found in <curl/curl.h>. This function gets called by |
5 | libcurl instead of its internal equivalent with a frequent |
6 | interval during operation (roughly once per second or sooner) |
7 | no matter if data is being transfered or not. Unknown/unused |
8 | argument values passed to the callback will be set to zero |
9 | (like if you only download data, the upload size will remain 0). |
10 | Returning a non-zero value from this callback will cause libcurl |
11 | to abort the transfer and return CURLE_ABORTED_BY_CALLBACK. |
12 | |
13 | If you transfer data with the multi interface, this function will |
14 | not be called during periods of idleness unless you call the |
15 | appropriate libcurl function that performs transfers. |
16 | |
17 | CURLOPT_NOPROGRESS must be set to 0 to make this function |
18 | actually get called. |
Dort kann ich dann abfragen ob innerhalb der letzten n Sekunden eine Antwort vom Server kam (jede Sekunde kommt etwas, wenn auch nur ein keep alive). Wenn nicht kommt breche ich einfach curl ab. Somit muss ich dann auch nichts in der main verändern. [edit] Bitte /code/-Abschnitte manuell umbrechen, sie sind sonst nicht sinnvoll lesbar. -rufus
A. R. schrieb: > Ich verwende Boost::Thread für Multithreads. > Hierbei gibt es keinen > close Befehl der den Thread zerstört. Das üblich Pattern ist folgendes:
1 | run() { |
2 | while(!this.stop) { |
3 | //do something
|
4 | }
|
5 | }
|
6 | |
7 | stopOperation() { |
8 | this.stop = true; |
9 | }
|
Man darf dann natürlich nicht mit blockierenden Operationen arbeiten. Einige Threadbibliotheken unterstützen auch das Konzept des Thread interupts, sodass man einen Thread auch in blockierenden Operation aus dem Schlaf reißen kann:
1 | run() { |
2 | try { |
3 | data = blockingRead(); |
4 | } catch(ThreadInteruptionException) { |
5 | //interupted while running...
|
6 | }
|
7 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.