HTTP-Download (paritial get, Head, unbekannte Dateigröße,...

Für allgemeine Fragen zur Programmierung mit PureBasic.
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Beitrag von GPI »

deMattin hat geschrieben:Denn bei Programmen mit Webabfragen/Downloads kommt man an Programmierung mit Threads ja leider nicht vorbei.
Wieso sollte man nicht?
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
deMattin
Beiträge: 87
Registriert: 30.08.2004 13:36
Wohnort: Ruhrpott
Kontaktdaten:

Beitrag von deMattin »

Na ganz einfach - weil die Webabfragen ja schon mal etwas dauern können und während dessen keine Userevents vom Programm angenommen werden.
OK - du arbeitest auch mit callbacks und es wäre durchaus möglich, dass das bei der Routine nicht erforderlich ist. So genau habe ich die Abläufe noch nicht analysiert.
Wenn man jedenfalls mit den normalen Win-APis arbeitet, kam ich ohne threads nicht aus - gerade dann, wenn es Probleme beim Abruf der Webinformation gibt! Die Benutzeingaben "hakeln" dann eben ziemlich.

Es kann aber auch andere Gründe für Threads geben und jede routine, die string-Thread-save ist, ist erstmal vorteilhaft.

In meinem aktuellen Projekt laufen auch webanfragen manchmal parallel und die GUI muss weiterhin voll verfügbar bleiben.

Zumindest die Abfrage der Webseite ansich ist bei dir wohl threadsicher, da hier mit buffern gearbeitet wird und keine stringoperationen gemacht werden. Schon ein einfacher space-befehl macht ja die routine schon für das threadproblem anfällig.

Ich werde dir deine routinen aber noch genauer anschauen und nach dem, was ich bisher so gesehen habe, ist das jedenfalls mit Abstand das Beste, was bisher in dem Bereich mit pb gemacht wurde - auch bzgl. Threadsicherheit bzw. Möglichkeit der Absicherung mit z.B. ss_threadsync.

Gruß,
Martin

PS: hast du dir das mit dem port nochmal angeschaut?
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Beitrag von GPI »

deMattin hat geschrieben:Na ganz einfach - weil die Webabfragen ja schon mal etwas dauern können und während dessen keine Userevents vom Programm angenommen werden.
Schlechte programmierung. Einzig und allein das opennetworkblabla() läßt das programm anhalten. Wenn du das Beispiel ansiehst: Du mußt in regelmäßigen abständen immer das download-doch-mal-ein-bischen-Routine aufrufen. Zwischenzeitlich kannst du mit window-event was machen.


>PS: hast du dir das mit dem port nochmal angeschaut?
bis jetzt nicht.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
deMattin
Beiträge: 87
Registriert: 30.08.2004 13:36
Wohnort: Ruhrpott
Kontaktdaten:

Beitrag von deMattin »

Schlechte programmierung...
Möchte ich nicht ausschliessen (zumindest in meinem Fall) :mrgreen:

Aber jeder macht eben nur so gut, wie er kann...

Aber in allen (eventuell) zeitaufwändigen Routinen nochmal einen event abzufragen, macht's auch nicht übersichtlicher ...

Wir brauchen über sinn- und unsinn von threads eigentlich hier auch nicht zu diskutieren. Wenn pb getrennte stringpointer je thread hätte, wär das eh kein thema ...

Ich versuche jedenfalls (gezwungenermaßen) meine threads zu reduzieren, wobei es aber schon eine prima Funktion der threads ist, eine Routine anzustossen und diese liefert dann laufend ihre Ergebnisse ohne den restlichen Programmablauf zu beeinflussen (theoretisch...)

Gruß
Martin

PS: Mein derzeitiges Hauptprojekt ist ein Program, dass ständig im Hintergrund arbeitet und gerade diese Hintergrundaktivitäten benutzen Webzugriffe und auch viele stringoperationen - und dann gibt's noch die GUI, von der aus parallel weiter Aktionen angestossen werden können, die die Hintergrundaktivitäten nicht beeinflussen sollen ...
Benutzeravatar
bluejoke
Beiträge: 1244
Registriert: 08.09.2004 16:33
Kontaktdaten:

Beitrag von bluejoke »

@GPI:
Ich habe auch immer Probleme mit Downloads die meine Schleife aufhalten.
Wie programmiert man das so, dass nix angehalten wird und dennoch keine Threads benutzt werden?

Am liebsten wäre mir sowas ähnliches wie Freaks Beispiel mit dem COM object nur dass die Events direkt in der Hauptschleife abgearbeitet werden können, also ohne Callback.


Simon
Ich bin Ausländer - fast überall
Windows XP Pro SP2 - PB 4.00
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Beitrag von GPI »

bsw. so:

Code: Alles auswählen

DoDownload=#False:StartDownload=#False
Repeat
  If DoDownload=#False
    event=WaitWindowEvent()
  Else
    Delay(1)
    event=WindowEvent()
  EndIf
  If event
    ;{ Window-event-handling
    ;}
  EndIf
  
  If StartDownload
    StartDownload=#False
    If HTTP_OpenUrl(Get.HTTPGetId,File$,url,WebPass$,ProxyServer$,ProxyPort,ProxyPass$,0) 
      DoDownload=#True
      Progress=0 
    EndIf
  EndIf
  
  If DoDownload
    If HTTP_ReceiveData(Get) 
      ;WindowEvent() 
      a=HTTP_GetProgress(Get) 
      If a<>Progress 
        PrintN("Progress: "+Str(a)+"%") 
        Progress=a 
      EndIf 
      ;if want abort 
      ; http_closeurl(get$) 
      ; printn("Abort") 
      ; break 2 
      ;endif 
    Else; Fertig
      DoDownload=#False
      ;Download fertig
      HTTP_CloseURL(Get) 
      ;{ Check
      
      Select HTTP_GetError(Get) 
        Case #URLError_OK:PrintN("Download complete") 
          ;{for memorydownload 
          ; OutBuffer=HTTP_GetOutBuffer(Get) 
          ; Size=HTTP_GetFileSize(Get) 
          ; Print("save to "+File$+".mem."+GetExtensionPart(File$)) 
          ; API_FileCreate(out.API_FileHandle,File$+".mem."+GetExtensionPart(File$)) 
          ; API_WriteData(out,OutBuffer,Size) 
          ; API_CloseFile(out) 
          ; FreeMemory(outbuffer) 
          ;} 
          PrintN(" done") 
          PrintN("") 
          PrintN("FileSize:"+Str(HTTP_GetFileSize(Get))) 
          PrintN("FileReceived:"+Str(Get\Received)) 
          PrintN("FileDate:"+FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss",HTTP_GetFileDate(Get))) 
        Case #URLError_OutOfMemory:PrintN("Out of memory") 
        Case #URLError_CantCreateFile:PrintN("Can't create file") 
        Case 301;Moved permanently 
          PrintN("Moved permanently:"+HTTP_GetNewLocation(Get)) 
          HTTP_ChangeURL(Get,HTTP_GetNewLocation(Get)) 
          If HTTP_ReConnect(Get); neu anfordern 
            DoDownload=#True
          Else 
            PrintN("Can't connect") 
          EndIf 
        Case 302;Moved temporarily 
          PrintN("Moved temporarily:"+HTTP_GetNewLocation(Get)) 
          HTTP_ChangeURL(Get,HTTP_GetNewLocation(Get)) 
          If HTTP_ReConnect(Get); neu anfordern 
            DoDownload=#True
          Else 
            PrintN("Can't connect") 
          EndIf 
        Case 305;Use Proxy 
          PrintN("Use Proxy:"+HTTP_GetNewLocation(Get)) 
        Case 401;unauthorized 
          PrintN("Unauthorized:"+HTTP_GetAuthenticateRealm(Get)) 
          Print(" UserName:"):user$=Input():PrintN("") 
          Print(" Password:"):pass$=Input():PrintN("") 
          If user$ 
            WebPass$=HTTP_CryptedUserPass(user$,pass$) 
            HTTP_ChangeWWWAuthenticate(Get,WebPass$) 
            If HTTP_ReConnect(Get); neu anfordern 
              DoDownload=#True
            Else 
              PrintN("Can't connect") 
            EndIf 
          Else 
            PrintN(" abort") 
          EndIf 
        Case 407;Proxy Authentication Required 
          PrintN("Proxy Authentication Required:"+HTTP_GetAuthenticateRealm(Get)) 
          Print(" UserName:"):user$=Input():PrintN("") 
          Print(" Password:"):pass$=Input():PrintN("") 
          If user$ 
            ProxyPass$=HTTP_CryptedUserPass(user$,pass$) 
            HTTP_ChangeProxyAuthenticate(Get,ProxyPass$) 
            If HTTP_ReConnect(Get); neu anfordern 
              DoDownload=#True
            Else 
              PrintN("Can't connect") 
            EndIf 
          Else 
            PrintN(" abort") 
          EndIf 
        Default 
          PrintN("ServerError:") 
          PrintN(Str(HTTP_GetError(Get))+" "+HTTP_GetErrorMessage(Get)) 
      EndSelect 
      ;}
      
    EndIf
  EndIf
ForEver
eventuell den buffer kleiner stellen

Code: Alles auswählen

If HTTP_OpenUrl(Get.HTTPGetId,File$,url,WebPass$,ProxyServer$,ProxyPort,ProxyPass$,1024) 
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Benutzeravatar
bluejoke
Beiträge: 1244
Registriert: 08.09.2004 16:33
Kontaktdaten:

Beitrag von bluejoke »

oh! schwerer Fehler von mir! Als ich nach einem Download mit Eventabfrage gefragt habe meinte ich einen solchen mit den API Funktionen.
Das es mit deinem Code funzt war mir klar, auch wenn ich den Code noch nicht angeschaut habe, aber ich glaube, ich habe was von wegen Prozessfortschrittsanzeige gelesen, was aufs selbe kommt.

Zum Abbrechen muss ich dann praktisch in die Evenabfrage reinschreiben:

Code: Alles auswählen

;Event: Abruch
 http_closeurl(get$)
 printn("Abort")
 break 2      ; brauch ich eigtl. hier nicht, oder?
 DoDownload=#False
;EndEvent
Das "break 2" heißt, das 2 Schleifen abgebrochen werden, oder wie?
Ich bin Ausländer - fast überall
Windows XP Pro SP2 - PB 4.00
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Beitrag von GPI »

bluejoke hat geschrieben: Das "break 2" heißt, das 2 Schleifen abgebrochen werden, oder wie?
Überbleibsel von anderen Code.

Edit: Sprich ist hier falsch und muß weg.
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
GPI
Beiträge: 1511
Registriert: 29.08.2004 13:18
Kontaktdaten:

Beitrag von GPI »

Einen Fehler in Code oben behoben (gab probleme mit manchen Proxys)
CodeArchiv Rebirth: Deutsches Forum Github Hilfe ist immer gern gesehen!
Spock
Beiträge: 1
Registriert: 01.01.2005 18:50

linux???

Beitrag von Spock »

hallo,

die API_xxxx proceduren scheinen nur unter windows zu funktionieren, mach ich da was falsch (bin neu bei purebasic)? oder sind das wiklich win32 api funktionen. wenn ja, hat schon mal jemand versucht das auf purebasic standardfunktionen umstustllne damit es auch unter linux klappt? oder ghet das garnicht?


mr. spock!
Antworten