Sign in to follow this  
Followers 0
delme

_TCPFileTransfer.au3

21 posts in this topic

#1 ·  Posted (edited)

Hey, this is just a little (but useful) script that I had posted here awhile ago, I recently updated it as it had a few major issues, but now it should be working correctly. All the info on how to use this is in the function headers below and in the headers in the file, hope you guys find this useful. If you find any bugs please let me know. Please feel free to post your questions and opinions bellow :).

To start an interrupted transfer from where it encountered an error you would do this:

$i = _TCPFileRecv($sock, "Randomfile.exe")
;*Gets interupted*
$newoffset = @extended ;@extended would be used to get the number of bytes successfully written to the file if an error had occured
;You need to communicate the number of bytes that were successfully recorded to the sending script somehow to make sure they send the file from the right offset, else the file will get corrupted. Just use a simple tcp message for this
$i = _TCPFileRecv($sock, "Randomfile.exe", $newoffset) ;start writing the file from where you left off

Here is the folder with the script examples:

_TCPFileTransfer.zip

and here is the _TCPFileTransfer.au3 file alone:

_TCPFileTransfer.au3

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.6.0
 Author:         DELmE

 Function:
    _TCPFileRecv

Description:
    Receives a file being sent over a TCP connection

Parameters:
    sock                The TCP socket to be used
    rFile               The name of the file to save to
    offset = 0          The offset to start writing data to the file at (to be used if the transfer is somehow interrupted) default value is 0 (no offset)
    $DataSize = 1024    The number of bytes of data to be received per packet, default value is 1024

Return value:
    Success     _TCPFileRecv returns the number of bytes written to the file
    Failure     _TCPFileRecv returns 0 if the function failed and sets @error to the following:
        1 = Error opening the file
        2 = Failed to set offset
        3 = Failed to receive data on socket (invalid socket)
        4 = Unable to write data to the file
        Also sets @extended to the number of bytes of data that was successfully written to the file

#ce ----------------------------------------------------------------------------

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.6.0
 Author:         DELmE

 Function:
    _TCPFileSend

Description:
    Sends a file over a TCP connection

Parameters:
    sock                The tcp socket to be used
    sFile               The file to be sent
    offset = 0          The offset to start reading data from the file at (to be used if the transfer is somehow interrupted) default value is 0 (no offset)
    $DataSize = 1024    The number of bytes of data to be sent per packet, default value is 1024

Return value:
    Success     _TCPFileSend returns the number of bytes sent
    Failure     _TCPFileSend returns 0 if an error occurred and sets @error to the following:
        1 = The file does not exist
        2 = Failed to set offset
        3 = Failed to read data from file
        4 = Failed to send data through socket
        Also sets @extended to the number of bytes of data that was successfully sent

#ce ----------------------------------------------------------------------------

Updates:

[5/16/2010] Changed the code completely, can now handle files of all sizes and supports offsets.

Edit:

Thanks to Manadar and FireFox for their help :)

Edited by DELmE

Share this post


Link to post
Share on other sites



Nearly 40 downloads and no comments? Anyone? :)

Share this post


Link to post
Share on other sites

Ok, I had a look at the library after your desperate plee. : )

But be warned, the code definitely needs some attention if you want other programmers to be able to use the library without modifying it.

$TCPSend = TCPSend($TCPConn, $oFileRead)
        If $TCPSend = 0 Then
            $error = True
        Else
            $buff = BinaryMid ($oFileOpen, $TCPSend + 1, BinaryLen ($oFileOpen) - $TCPSend)
            Do
                $TCPSend = TCPSend($TCPConn, $buff)
                $buff = BinaryMid ($buff, $TCPSend + 1, BinaryLen ($buff) - $TCPSend)
            Until $buff = ""
        EndIf

I'm not sure if I fully understand how this works, but it seems to me that you're trying to send the entire file in one piece ( regardless of size ) first and if that fails you are sending it in chunks; Why not send it in chunks immediately? The benefit of chunks is that the application will not hang and you can check for errors during the transfer. If an error occurs you should be able to reconnect and continue the file transfer on a new socket.

$TCPRecv = TCPRecv($TCPAcc, 9999999)
;------------------------------^

Why 9999999? Numbers like this that make no sense and should be avoided always. As a last resolution you can always ( this is bad too ): Dim Const $Infinite = 999999;

TCPStartup()
TCPShutdown()

These two, I understand they are necessary; but give the programmer who is using the library the choice when to start up or when to shut down. Maybe he is using other TCP connections in his application and suddenly his socket is closed for no reason.

Proposed solution: Remove the startup and shutdown, and tell the programmer to do it him self! : )

AutoItSetOption("TCPTimeout", 2000)

Again this might conflict with what the rest of the script is doing. You can reset the original option when your transfer is finished. Look this up in help file.

Do
        $TCPAcc = TCPAccept($TCPListen)
        $TCPRecv = TCPRecv($TCPAcc, 9999999)
        $TCPDiff = TimerDiff($TCPTimerInt)
        If $TCPDiff >= $sTimeout Then
            $error = True
            ExitLoop
        EndIf
    Until $TCPRecv <> ""

This time out is unnecesary. If the connection stays open then the receiver should just be patient until the TCP connection closes by itself or the transfer is finished.

And last one:

If X Then Y
If Not X Then Z

You do this a lot, but it causes the expression to be evaluated twice! One time is enough, so do this instead:

If X Then
   Y
Else
   Z
EndIf

You are definitely on your way to writing a good and simple to use library! For a beginner user of AutoIt I am already impressed.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Ok, I had a look at the library after your desperate plee. : )

But be warned, the code definitely needs some attention if you want other programmers to be able to use the library without modifying it.

$TCPSend = TCPSend($TCPConn, $oFileRead)
        If $TCPSend = 0 Then
            $error = True
        Else
            $buff = BinaryMid ($oFileOpen, $TCPSend + 1, BinaryLen ($oFileOpen) - $TCPSend)
            Do
                $TCPSend = TCPSend($TCPConn, $buff)
                $buff = BinaryMid ($buff, $TCPSend + 1, BinaryLen ($buff) - $TCPSend)
            Until $buff = ""
        EndIf

I'm not sure if I fully understand how this works, but it seems to me that you're trying to send the entire file in one piece ( regardless of size ) first and if that fails you are sending it in chunks; Why not send it in chunks immediately? The benefit of chunks is that the application will not hang and you can check for errors during the transfer. If an error occurs you should be able to reconnect and continue the file transfer on a new socket.

$TCPRecv = TCPRecv($TCPAcc, 9999999)
;------------------------------^

Why 9999999? Numbers like this that make no sense and should be avoided always. As a last resolution you can always ( this is bad too ): Dim Const $Infinite = 999999;

TCPStartup()
TCPShutdown()

These two, I understand they are necessary; but give the programmer who is using the library the choice when to start up or when to shut down. Maybe he is using other TCP connections in his application and suddenly his socket is closed for no reason.

Proposed solution: Remove the startup and shutdown, and tell the programmer to do it him self! : )

AutoItSetOption("TCPTimeout", 2000)

Again this might conflict with what the rest of the script is doing. You can reset the original option when your transfer is finished. Look this up in help file.

Do
        $TCPAcc = TCPAccept($TCPListen)
        $TCPRecv = TCPRecv($TCPAcc, 9999999)
        $TCPDiff = TimerDiff($TCPTimerInt)
        If $TCPDiff >= $sTimeout Then
            $error = True
            ExitLoop
        EndIf
    Until $TCPRecv <> ""

This time out is unnecesary. If the connection stays open then the receiver should just be patient until the TCP connection closes by itself or the transfer is finished.

And last one:

If X Then Y
If Not X Then Z

You do this a lot, but it causes the expression to be evaluated twice! One time is enough, so do this instead:

If X Then
   Y
Else
   Z
EndIf

You are definitely on your way to writing a good and simple to use library! For a beginner user of AutoIt I am already impressed.

Thanks for the indepth help! I will definatly take another look at the script and fix it up using all the suggestions you just gave me :)

Edited by DELmE

Share this post


Link to post
Share on other sites

Very useful! thanks"


Console Browse: Navigate on the WEB in a textual consoleMultiPing!: Show computer on the lan and/or show the local/remote task, ALL animated!KillaWin: Event executingCryptPage: Crypt your webpage and show only with key

Share this post


Link to post
Share on other sites

Very useful! thanks"

Thanks :) Im fixing it up with Manadar's suggestions at the moment to make it more user friendly :)

Share this post


Link to post
Share on other sites

Manadar:

I've just finished fixing up the areas that you pointed out to me but now when I transfer exe's they, for some reason, increase in size during transfer and no-longer work. I checked with my old version and found that the same thing happened when transfering larger files. This leads me to think that it has something with the way I am using the BinaryMid() function. Heres what I have:

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.0.0
 Author:         DELmE

 Script Function:
    _TCPFileRecv
    
Description:
    Receives a file being sent over a TCP connection
    
Parameters:
    rFile       The name of the file to save to
    Ip          The Ip to listen on for the file (default = @IPAddress1)
    Port        The port to listen on for incoming file data (default = 7894)
    
Return value:
    Success     _TCPFileRecv returns 1 if the file was successfully received and written
    Failure     _TCPFileRecv returns 0 if the function failed

#ce ----------------------------------------------------------------------------
Func _TCPFileRecv($rFile, $Ip = @IpAddress1, $Port = 7895)
    If $Ip = "" Then $Ip = @IpAddress1
    If $Ip = -1 Then $Ip = @IpAddress1
    If $Port = "" Then $Port = 7894
    If $Port = -1 Then $Port = 7894
    $opt = AutoItSetOption("TCPTimeout", 2000)
    Local $error = False
    Local $buff
    
    $TCPListen = TCPListen($Ip, $Port)
        
    $no_recv_count = 0
    
    $TCPAcc = TCPAccept($TCPListen)
    Do
        $TCPRecv = TCPRecv($TCPAcc, 100000)
        If $TCPRecv = "" Then
            $no_recv_count += 1
        Else
            $buff &= $TCPRecv
            $no_recv_count = 0
        EndIf
    Until $no_recv_count >= 15
    
    If $buff = "" Then
        $error = True
    Else
        $rFileOpen = FileOpen($rFile, 16 + 2)
        If $rFileOpen = -1 Then
            $error = True
        Else
            $rFileWrite = FileWrite($rFileOpen, $buff)
            If $rFileWrite = 0 Then
                $error = True
            EndIf
            FileClose($rFileOpen)
        EndIf
    EndIf
    TCPCloseSocket($TCPListen)
    AutoItSetOption("TCPTimeout", $opt)
    If $error = True Then
        Return 0
    Else
        Return 1
    EndIf
EndFunc ;==> _TCPFileRecv

#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.0.0
 Author:         DELmE

 Script Function:
    _TCPFileSend

Description:
    Sends a file over a TCP connection

Parameters:
    sFile       The file to be sent
    Ip          The Ip to send on (default = @IPAddress1)
    Port        The port to send the file data on (default = 7894)

Return value:
    Success     _TCPFileSend returns 1 if the file was successfully sent out
    Failure     _TCPFileSend returns 0 if an error occurred

#ce ----------------------------------------------------------------------------
Func _TCPFileSend($sFile, $Ip = @IPAddress1, $Port = 7895)
    If $Ip = -1 Then $Ip = @IPAddress1
    If $Ip = "" Then $Ip = @IPAddress1
    If $Port = -1 Then $Port = 7894
    If $Port = "" Then $Port = 7894
    $opt = AutoItSetOption("TCPTimeout", 2000)
    Local $error = False
    $sFileOpen = FileOpen($sFile, 16 + 0)
    $sFileRead = FileRead($sFileOpen)
    FileClose($sFileOpen)
    $sFileSize = BinaryLen($sFileRead)
    
    $TCPConn = TCPConnect($Ip, $Port)
    If $TCPConn = -1 Then
        $error = True
    Else
        If $sFileSize < 100000 Then
            $TCPSend = TCPSend($TCPConn, $sFileRead)
            If $TCPSend = 0 Then
                $TCPConn = TCPConnect($Ip, $Port)
                $TCPSend = TCPSend($TCPConn, $sFileRead)
            EndIf
        Else
            $buff = $sFileRead
            Do
                $TCPSend = TCPSend($TCPConn, BinaryMid($buff, 1, 100000))
                If $TCPSend = 0 Then
                    $TCPConn = TCPConnect($Ip, $Port)
                    $TCPSend = TCPSend($TCPConn, BinaryMid($buff, 1, 100000))
                EndIf
                $buff = BinaryMid($buff, $TCPSend + 1)
            Until BinaryLen($buff) = 0
        EndIf
    EndIf
    TCPCloseSocket($TCPConn)
    AutoItSetOption("TCPTimeout", $opt)
    If $error = True Then
        Return 0
    Else
        Return 1
    EndIf
EndFunc ;==> _TCPFileSend

Any chance you (or anyone else who may be reading this) can point me in the right direction?

Thanks :)

Share this post


Link to post
Share on other sites

@DELmE

Take a look here : http://www.autoitscript.com/forum/index.php?showtopic=89679

Cheers, FireFox.


 

OS : Win XP SP2 (32 bits) / Win 7 SP1 (64 bits) / Win 8 (64 bits) | Autoit version: latest stable / beta.
Hardware : Intel(R) Core(TM) i5-2400 CPU @ 3.10Ghz / 8 GiB RAM DDR3.

My UDFs : Skype UDF | TrayIconEx UDF | GUI Panel UDF | Excel XML UDF | Is_Pressed_UDF

My Projects : YouTube Multi-downloader | FTP Easy-UP | Lock'n | WinKill | AVICapture | Skype TM | Tap Maker | ShellNew | Scriptner | Const Replacer | FT_Pocket | Chrome theme maker

My Examples : Capture toolIP Camera | Crosshair | Draw Captured Region | Picture Screensaver | Jscreenfix | Drivetemp | Picture viewer

My Snippets : Basic TCP | Systray_GetIconIndex | Intercept End task | Winpcap various | Advanced HotKeySet | Transparent Edit control

 

Share this post


Link to post
Share on other sites

Hey, I'm going to be away for about 4 or 5 days so if you have any questions or comments I'll reply to them when I can :)

DELmE

Share this post


Link to post
Share on other sites

Just got back :) .

What did you guys think? (the people who saw the thread before it went to page 2 :) )

Share this post


Link to post
Share on other sites

Hi!

I have a problem >_<

With big file (more than 19 mega) the script goes in "memory error" :(

Is there a solution?

thanks!


Console Browse: Navigate on the WEB in a textual consoleMultiPing!: Show computer on the lan and/or show the local/remote task, ALL animated!KillaWin: Event executingCryptPage: Crypt your webpage and show only with key

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Hi!

I have a problem >_<

With big file (more than 19 mega) the script goes in "memory error" :(

Is there a solution?

thanks!

Hmm. I dunno what that is. Never happened to me. Do you have any other programs open that are using TCP or UDP?

Edit: I'm thinking that it may be because while the file is being sent the data is stored in a variable and maybe 19MB of data passes the length that AutoIt can carry in a variable, just taking a stab though as I don't really know..

Edited by DELmE

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Gob jobS. Thanks.

But i encounter some problems.

Success when i used it to transfer .txt files.

Fail when i used it to transfer .rar or .exe files.

Edited by Xwolf

Share this post


Link to post
Share on other sites

Currently updating this code so that it will be able to handle files of any size, and will be able to re-start an interrupted transfer from where it was left off.

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

Finished the update, just scrapped the old version and wrote a new one :idea:. The code is now 100 times better :)

Edited by DELmE

Share this post


Link to post
Share on other sites

I have done basic test. A file (*.tar.gz) with 86MB pass successfully via my company network.


Be Green Now or Never (BGNN)!

Share this post


Link to post
Share on other sites

I have done basic test. A file (*.tar.gz) with 86MB pass successfully via my company network.

Cool, good to hear :idea:

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

Hey guys,

I'm having some problems with the server:

I tried to transfer a file over the internet using my external IP and an open port.

What happens is that sometimes, everything works just perfectly, but often the server does not close the file handle after the transfer has finished.

You send a "close handle" request to the server with those two line breaks (line 147 I think). I tried using a different string for the request and replaced

If $rBuff = "WMpHUWr0FEZg" Then

with

If stringright($rBuff,12) = "WMpHUWr0FEZg" Then

which made it a little more reliable, but it still doesn't work every time.

Any ideas?

Edited by TheBrainiac

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

very very useful this UDF, but you can implement a function of ProgressOn? It would be nice to be able to see how to get the bits in a progressbar.

thanks !

Edited by incepator

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