Sign in to follow this  
Followers 0
Koder

Inetget() Works Differently In V3.1.1.119 (beta)

8 posts in this topic

InetGet() never needed a long pause before @InetGetBytesRead would work properly, I normally use 50 milliseconds. Now it needs at about 500. Why would @InetGetBytesRead return -1 if @InetGetActive is 1?

In my script I check the files size (for a progress bar), then download the file.

This works with NO problems whatsoever in build 118.

Increasing the Sleep() fixes the problem, but how do I know it will work on other machines? A timing problem could be different on different machines. Would a slower Inet connection need a longer sleep time?

Here's a cleaned up fragment. The error occurs at $LastBytes = @InetGetBytesRead, which in beta 119 reports -1 (if not paused long enough).

For $i = 1 to $count
    $URL = "FTP:\\Ftp.URL.net\path\" & $Files[$i]

    $size = InetGetSize($URL)

    If @error == 1 Then
    ; report error
        msg(0,0,"Error: " & $Files[$i])
        ExitLoop
    EndIf

    ProgressSet(0, "", "")

; Send FTP command to download file
    $rc = InetGet($URL, $Local & "\" & $Files[$i], 0, 1)
    If @error == 1 Then
        msg(0,0,"Error: " & $Files[$i])
        Exit(1)
    EndIf

    Sleep(50); Error occurs if this sleep is too short... never needed to be any longer than 0 (zero)

    While @InetGetActive
        Sleep(10)

        $LastBytes = @InetGetBytesRead ; Reports -1 if sleep() is too short, but not in 118
        If @InetGetBytesRead == -1 Then
            MsgBox(16, 0, "Download error!" & @CR & @InetGetBytesRead & @CR & $Files[$i])
            ExitLoop
        EndIf
        ProgressSet((@InetGetBytesRead / $size) * 100, "", "")
    Wend
Next

Thanks!

Rick

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

This block of code is pointless for two reasons:

; Send FTP command to download file
    $rc = InetGet($URL, $Local & "\" & $Files[$i], 0, 1)
    If @error == 1 Then
        msg(0,0,"Error: " & $Files[$i])
        Exit(1)
    EndIf

First reason, InetGet() can set @error to more than just 1. Also, the error codes of InetGet() are undocumented and should not be used. If you need to know if InetGet() succeeded or not, use the return value.

Second reason, calling InetGet() with the background mode parameter won't cause @error to be set at all. It also won't return any other value except 1.

To answer your question, the download hasn't started. @InetGetBytes is set to -1 from the time InetGet() is started up until the function establishes communication wit the remote host. Then it will be set to 0 and the download loop is started. So that means there is a flaw in your logic. You shouldn't be checking the value of @InetGetBytesRead and treating it as an error condition while a download is active. If a download is active, then it's still active and no error has occurred yet. The value returned by @InetGetBytesRead only denotes that an error occurred connecting to the remote host after the download is terminated (meaning @InetGetActive is no longer true).

I chalk this up to mis-leading documentation.

You don't need the Sleep() at all and the last block of code should be:

While @InetGetActive
        Sleep(10)
        $LastBytes = @InetGetBytesRead; Reports -1 if sleep() is too short, but not in 118
        If $LastBytes = -1 Then $LastBytes = 0
        ProgressSet(($LastBytes / $size) * 100, "", "")
    Wend
    If @InetGetBytesRead = -1 Then
        MsgBox(16, 0, "Download error!" & @CR & @InetGetBytesRead & @CR & $Files[$i])
    EndIf

I'm inclined to remove the -1 altogether. If a user knows a download is supposed to occur, then checking if @InetGetBytesRead = 0 after their @InetGetActive loop should be a signal the download has occurred. Otherwise, as demonstrated in the revised fragment above, we are going to have to manually catch a -1 byte count and convert it to 0 to make sure progress calculations don't end up being weird.

Edit: On second thought, I just thought of a way to change the code so that your code will continue to work without the Sleep() statement.

Edited by Valik

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Hey, thanks for the info, I would have kept using @error and never nocticed a download problem until later.

Shouldn't @InetGetBytesRead return -1 only when an error has occurred? and return 0 while the connection is still being negotiated? If the connection later fails, -1 would be informative. Otherwise @InetGetBytesRead = -1 means different things during the course of the download. I could check for -1 at the start of the loop, but then what if it's a real error? Does @InetGetActive change to 0 at the same time?

With @InetGetBytesRead = 0 until the connection starts, there is no special case required and @InetGetBytesRead can be used directly without being cleaned up from -1.

So the real question is, what does a real error look like (if it occurs during a download that starts normally)?

Ok, I've coded the answer to my question below and yes, this does work. But I still have no way of knowing what a real error will look like. Do I know that @InetGetActive wil change to 0 when my network cable is pulled out?

$rc = InetGet($URL, $Local & "\" & $Files[$i], 0, 1)
while @InetGetActive
        $LastBytes = @InetGetBytesRead
    if @InetGetActive == 1 AND $LastBytes == -1 Then
    ; Not an Error?
    ; server still connecting?
          $LastBytes = 0; prevents progress bar from using -1
    ElseIf @InetGetActive == 0 AND $LastBytes == -1 Then
; Real error?
; Hard to test, pull the NIC cable on a large file?
         exitloop
    Endif
    ProgressSet(($LastBytes / $size) * 100, "", "")   
wend
if @InetGetBytesRead == -1 Then
; Real error
endif

By the way this code fragment is intentionally, unnecessarily complicated. Valik, your example is better. I'm only complaining a bit about -1 not being a real error.

Thanks!

Rick

Edited by Koder

Share this post


Link to post
Share on other sites

Essentially, the correct way to write a download loop is (in pseudo-code):

$size = InetGetSize()
InetGet()
While @InetGetActive
  ; Wait for download to finish
WEnd
If @InetGetBytesRead <> $size Then MsgBox(4096, "", "Error occurred")

Checking against the hard-coded value of -1 is the wrong thing to do and always has been. You really should be checking that the size after the download is equal to the size of the file.

That being said, I'm going to modify the code so that it sets @InetGetBytesRead to 0 up until the download starts. Once the download starts, then it will begin counting the bytes downloaded. If an error occurs during the middle of the download, @InetGetBytesRead will not be reset to -1, it will be the total bytes read up until the point of the error. If an error occurs before the download actually starts, @InetGetBytesRead will be set to -1 to signify an error. This change should allow your original code to continue to work without any sleep statements between InetGet() and the While loop.

In any case, the example I provided above shows the correct way to monitor a download regardless of which version of AutoIt you're using. I will also add that example to the documentation.

Share this post


Link to post
Share on other sites

Essentially, the correct way to write a download loop is (in pseudo-code):

$size = InetGetSize()
InetGet()
While @InetGetActive
 ; Wait for download to finish
WEnd
If @InetGetBytesRead <> $size Then MsgBox(4096, "", "Error occurred")

Checking against the hard-coded value of -1 is the wrong thing to do and always has been. You really should be checking that the size after the download is equal to the size of the file.

That being said, I'm going to modify the code so that it sets @InetGetBytesRead to 0 up until the download starts. Once the download starts, then it will begin counting the bytes downloaded. If an error occurs during the middle of the download, @InetGetBytesRead will not be reset to -1, it will be the total bytes read up until the point of the error. If an error occurs before the download actually starts, @InetGetBytesRead will be set to -1 to signify an error. This change should allow your original code to continue to work without any sleep statements between InetGet() and the While loop.

In any case, the example I provided above shows the correct way to monitor a download regardless of which version of AutoIt you're using. I will also add that example to the documentation.

Hi Valik,

While you are into that (I haven't researched this because I didn't think of it until I was reading your post) is there anything that can be done to allow (if it isn't already available) a progress bar reflecting the download or even a simple update of bits/bytes downloaded? If that isn't possible, is there a way (that the average Joe could come up with) to do something similar with existing capabilities. Notice I didn't ask what it is.

Gene :think:


[font="Verdana"]Thanks for the response.Gene[/font]Yes, I know the punctuation is not right...

Share this post


Link to post
Share on other sites

Hi Valik,

While you are into that (I haven't researched this because I didn't think of it until I was reading your post) is there anything that can be done to allow (if it isn't already available) a progress bar reflecting the download or even a simple update of bits/bytes downloaded? If that isn't possible, is there a way (that the average Joe could come up with) to do something similar with existing capabilities. Notice I didn't ask what it is.

Gene :think:

http://www.autoitscript.com/forum/index.ph...ndpost&p=141934

[center]Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.[/center]

Share this post


Link to post
Share on other sites

Hi Valik,

While you are into that (I haven't researched this because I didn't think of it until I was reading your post) is there anything that can be done to allow (if it isn't already available) a progress bar reflecting the download or even a simple update of bits/bytes downloaded? If that isn't possible, is there a way (that the average Joe could come up with) to do something similar with existing capabilities. Notice I didn't ask what it is.

Gene :think:

That's the kind of stuff that gets done in the While loop and far exceeds the scope of a downloading function. That's also the reason there is a macro for getting the number of bytes downloaded and another function for getting the size from the server. It's trivial to calculate all that stuff.

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Just a quick update, I've made the changes to fix this issue and things should be working just like they were previously with the new code. If an error occurs, @InetGetBytesRead will be set to -1 unconditionally. This includes setting the value to -1 when an error occurs in the middle of a file transfer. Previously I stated the counter would be left alone but that is not how AutoIt has ever worked so I'm not going to change that behavior.

Once I upload these changes, the function should work identical to previous versions. I have more work to do on InetGet() but the changes should be in the next version of AutoIt and no later than 2 versions away.

Edited by Valik

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0