Results 1 to 22 of 22

Thread: Visual Basic - Send File With Winsock

  1. #1

    Thread Starter
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Post Visual Basic - Send File With Winsock

    Just a small code snippet to transfer the contents of a file over a Winsock connection (the socket must first be connected). Here is a brief description of the parameters:

    SendFile(SocketObject As Variant, FilePath As String, PacketSize As Long)

    • SocketObject - The winsock control you will be using to send the file. It is passed as a variant so you can use a winsock control that is part of an array, or one that isn't.
    • FilePath - The full path to the file you are sending.
    • PacketSize - The amount of data to send at once, or in one packet. The file is sent in seperate chunks, and this specifies how many bytes to send at a time. For slower connections, like 56k, you will want to make this a small number, like 512 (1/2 KB) or 1024 (1 KB). For high speed internet connections you can make it much larger.


    Code:
    Public Sub SendFile(SocketObject As Variant, ByVal FilePath As String, ByVal PacketSize As Long)
    Dim lonFF As Long, bytData() As Byte
    Dim lonCurByte As Long, lonSize As Long
    Dim lonPrevSize As Long
    
    On Error GoTo ErrorHandler
    
    lonSize = FileLen(FilePath)
    
    Open FilePath For Binary Access Read As #lonFF
        
        ReDim bytData(1 To PacketSize) As Byte
        
        Do Until (lonSize - lonCurByte) < PacketSize
            Get #lonFF, lonCurByte + 1, bytData()
            lonCurByte = lonCurByte + PacketSize
            SocketObject.senddata bytData()
            DoEvents
        Loop
        
        lonPrevSize = lonSize - lonCurByte
        
        If lonPrevSize > 0 Then
            ReDim bytData(1 To lonPrevSize) As Byte
            Get #lonFF, lonCurByte + 1, bytData()
            lonCurByte = lonCurByte + lonPrevSize
            SocketObject.senddata bytData()
        End If
    
    Close #lonFF
    Exit Sub
    
    ErrorHandler:
        Debug.Print "Send File Error"
        Debug.Print "---------------"
        Debug.Print "Number:      " & Err.Number
        Debug.Print "Description: " & Err.Description
        Debug.Print "File:        " & FilePath
        
    End Sub

  2. #2
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,802

    Re: Visual Basic - Send File With Winsock

    That code will work only for small files.
    Since you are not waiting until you receive the "SendComplete" event from winsock, the winsock internal buffer will overflow after a while. I'm not sure how big the winsock buffer is though.
    I am writing this ONLY because I don't want people who don't know anything about winsock, to learn the wrong way to do this.
    The right way to transfer a file of any size, is to wait for the "SendComplete" event from winsock, then send another chunk. You will also have to use a timer, because you can't call the Winsock.SendData sub from the SendComplete event.

    Anyways... beginners don't use this code ! only if you know what you are doing, then use it...

  3. #3
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,802

    Re: Visual Basic - Send File With Winsock

    THE RIGHT WAY TO DO IT !

    I did not actually test this, but it should work...
    VB Code:
    1. Option Explicit
    2.  
    3. Private iFileNum As Integer, lPacketSize As Long
    4.  
    5. Public Sub SendFile(SocketObject As Winsock, ByVal FilePath As String, Optional ByVal PacketSize As Long = 1024)
    6.     Dim Buffer() As Byte
    7.    
    8.     lPacketSize = PacketSize ' save the PacketSize for the timer
    9.     Timer1.Enabled = False ' make suze timer is not enabled
    10.    
    11.     iFileNum = FreeFile ' get free file number
    12.     Open FilePath For Binary Access Read As iFileNum ' open file
    13.    
    14.     ' if file size is smaller than PacketSize, then send the whole file, but not more
    15.     ReDim Buffer(lngMIN(LOF(iFileNum), PacketSize) - 1)
    16.     Get iFileNum, , Buffer ' read data
    17.    
    18.     SocketObject.SendData Buffer ' send data
    19. End Sub
    20.  
    21. Public Function lngMIN(ByVal L1 As Long, ByVal L2 As Long) As Long
    22.     If L1 < L2 Then
    23.         lngMIN = L1
    24.     Else
    25.         lngMIN = L2
    26.     End If
    27. End Function
    28.  
    29. Private Sub Timer1_Timer()
    30.     Dim Buffer() As Byte, BuffSize As Long
    31.    
    32.     Timer1.Enabled = False
    33.     If iFileNum <= 0 Then Exit Sub
    34.    
    35.     If Loc(iFileNum) >= LOF(iFileNum) Then ' FILE COMPLETE
    36.         Close iFileNum ' close file
    37.         iFileNum = 0 ' set file number to 0, timer will exit if another timer event
    38.        
    39.         Exit Sub
    40.     End If
    41.    
    42.     'if the remaining size in the file is smaller then PacketSize, the read only whatever is left
    43.     BuffSize = lngMIN(LOF(iFileNum) - Loc(iFileNum), lPacketSize)
    44.    
    45.     ReDim Buffer(BuffSize - 1) ' resize buffer
    46.     Get iFileNum, , Buffer ' read data
    47.     SocketObject.SendData Buffer ' send data
    48.    
    49.     ' Show progress
    50.     Me.Caption = Format(Loc(iFileNum) / CDbl(LOF(iFileNum)) * 100#, "#0.00") & "% Done"
    51.    
    52.     ' timer event will be called again when last packet is sent, close the file then
    53. End Sub
    54.  
    55. Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
    56.     ' read incomming data here...
    57. End Sub
    58.  
    59. Private Sub Winsock1_SendComplete()
    60.     ' can't call SendData here, so enable timer to do it...
    61.     Timer1.Enabled = False
    62.     Timer1.Interval = 1
    63.     Timer1.Enabled = True
    64. End Sub

  4. #4

    Thread Starter
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: Visual Basic - Send File With Winsock

    Sorry, but the TCP buffer will not overflow using my code.

    Sending only 1024 bytes at a time makes it impossible for the buffer to overflow, even on slower connections considering the TCP buffer is 32768 bytes in size (over 32 MB) no connection can even transmit enough data to make it overflow, even over a LAN...

    No offense, but using a timer is one of the worst ways to go about it. If you're going to wait for the SendComplete() event to fire, you should use a boolean flag variable and a do/until loop until the data has been trasmitted...ie:

    SendData bytBuffer()
    bolSending = True

    Do
    DoEvents
    Loop Until bolSending = False

    .....

    Sub Winsock_SendComplete()
    bolSending = False
    'Transer will continue from this point.

  5. #5
    New Member
    Join Date
    Nov 2005
    Posts
    1

    Re: Visual Basic - Send File With Winsock

    The sendcomplete event does not guarantee that the data has been received by the destination, only that it has been sent by the sending app

  6. #6
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,802

    Re: Visual Basic - Send File With Winsock

    Quote Originally Posted by souren
    The sendcomplete event does not guarantee that the data has been received by the destination, only that it has been sent by the sending app
    Ammm... yes it does... or are you talking about UDP ?

  7. #7
    New Member
    Join Date
    Oct 2006
    Posts
    6

    Re: Visual Basic - Send File With Winsock

    Quote Originally Posted by DigiRev
    Sorry, but the TCP buffer will not overflow using my code.

    Sending only 1024 bytes at a time makes it impossible for the buffer to overflow, even on slower connections considering the TCP buffer is 32768 bytes in size (over 32 MB) no connection can even transmit enough data to make it overflow, even over a LAN...

    No offense, but using a timer is one of the worst ways to go about it. If you're going to wait for the SendComplete() event to fire, you should use a boolean flag variable and a do/until loop until the data has been trasmitted...ie:

    SendData bytBuffer()
    bolSending = True

    Do
    DoEvents
    Loop Until bolSending = False

    .....

    Sub Winsock_SendComplete()
    bolSending = False
    'Transer will continue from this point.
    hello, i've come across a similar problem with a multiplayer game im making, it seems the data gets appended when its sent too fast with winsock, i thought this same idea and logic for resolving the issue but i wanted to confirm it. now that im thinking and have seen your code, you have an infinite loop
    Do
    DoEvents
    Loop Until bolSending = False

    if for some reason the sendcomplete is not triggered(maybe a winsock error or disconnect??) then the program would get locked. or everytime you use the send data method its always 100% completed? even if the connection is lost?? even if not connected a few milliseconds before??

    well im thinking about using timegettime or a similar system function to specify a timeout in milliseconds, just in case the program would get stuck and then display a timeout sending data msg in the server's log.

    the other solution i have seen around is to put another character at the end and split but to me seems like a bad solution to be sending an extra byte for every msg or even more when they append,but somehow i think this would never delay the send, ever..but i hope that making a loop would slow down the least as possible...a couple of ms i think. not more than 10-25 ms hopefully.

  8. #8
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,802

    Re: Visual Basic - Send File With Winsock

    I agree with all the points you've made, and that's why I said that that code is not good.

    It is much safer to use a timer the way I showed in post #3

  9. #9
    New Member
    Join Date
    Oct 2006
    Posts
    6

    Re: Visual Basic - Send File With Winsock

    Quote Originally Posted by CVMichael
    I agree with all the points you've made, and that's why I said that that code is not good.

    It is much safer to use a timer the way I showed in post #3
    while your code is safe, and good for an app and for sending files in this case for a multiplayer game and sending just game data i believe is not good to use timer controls. because i would have to load a new timer control instance wich will quickly drain a lot of memory from the server and they are not fast like system timer functions. in my case its more simple because i just want to send normal data. i believe i have to specify in the server program a timeout variable, and i would type in the desired milliseconds to wait for the sendcomplete and it would not get stuck or have to load a timer control wich is complicated and not so professional for a game.

    i unless someone can tell me im wrong and its not necessary to worry about the sendcomplete method failing.

    another thing im thinking is if to store the confirmation of the sending in an dynamic array of booleans or just to use the tag property of the winsocks array for that. wich is faster? any suggestions on that?

  10. #10

    Thread Starter
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: Visual Basic - Send File With Winsock

    This code wasn't intended as a function to solve all of your file-transfer needs. It was just an example of how to transfer the contents of a file over a winsock connection. Of course you will have to modify a few things to suit whatever it is you're doing.

    You may want to add a timeout procedure incase the socket gets disconnected, or encounters an error. ie:

    Do
    DoEvents
    Loop Until Sending = False Or TimeOut = True

    If you want to use a timer to send the file, it will work but it isn't the best way to go about it. The timer tells you nothing about wether or not the data was sent completely or not, the SendComplete() and SendProgress() events do (that's what they're intended for )

    Anyway, I've started on a file sender/receiver ActiveX control so I'll post that here when it's finished. It will be much more reliable than this code.

  11. #11

    Thread Starter
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: Visual Basic - Send File With Winsock

    Quote Originally Posted by mu_ds
    i unless someone can tell me im wrong and its not necessary to worry about the sendcomplete method failing.
    I've never had the SendComplete() event fail. If it does, it's because there was a socket error, which means the Socket_Error() event will fire, in which case, you should use for error handling.

    another thing im thinking is if to store the confirmation of the sending in an dynamic array of booleans or just to use the tag property of the winsocks array for that. wich is faster? any suggestions on that?
    If you're using multiple sockets in an array, you could use the .Tag property, but it would be faster/more effecient to use a boolean array. Although the speed difference probably wouldn't be noticeable.

  12. #12
    New Member
    Join Date
    Jun 2007
    Posts
    11

    Re: Visual Basic - Send File With Winsock

    Hi CVMicheal,

    For your post at 04-02-2005, 11:31 PM, code line 15
    it wrote
    ReDim Buffer(lngMIN(LOF(iFileNum), PacketSize) - 1)

    Is it more correct if we put
    ReDim Buffer(lngMIN(LOF(iFileNum)-LOC(iFileNum), PacketSize) - 1)

    ?

  13. #13
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,802

    Re: Visual Basic - Send File With Winsock

    I don't see why to put the Loc(iFileNum) when you just opened the file, and Loc(iFileNum) is always at the beginning of the file...

    Loc(iFileNum) returns the cursor location
    Lof(iFileNum) returns the file size

    At line 43 is needed because we already read some data from the file...

  14. #14
    New Member
    Join Date
    Jun 2007
    Posts
    11

    Re: Visual Basic - Send File With Winsock

    Hi CVMichael, you are right. Thanks The crucial line is at line 43.

    I missed the timer part because I implement it as a do while loop with a boolean flag which was mentioned by DigiRev, but referencing your send complete methodology. This is due to I do this in the vba form, and it only has 1 general timer, and I have used it for other purposes.
    Hence for my case, it is important to set the boolean flag(to the value that will make it go out of busy waiting in the while...wend loop) in any potential ending places and within the error handler.

    Thanks for the posts, it is very helpful

  15. #15
    New Member
    Join Date
    May 2007
    Posts
    8

    Re: Visual Basic - Send File With Winsock

    hi, in this code does it send the contents of the file or the file itself? Im making a program to login using the file contents, reading it and sending the info with sck.SendData.

  16. #16

    Thread Starter
    "Digital Revolution"
    Join Date
    Mar 2005
    Posts
    4,471

    Re: Visual Basic - Send File With Winsock

    Quote Originally Posted by canadadoya
    hi, in this code does it send the contents of the file or the file itself? Im making a program to login using the file contents, reading it and sending the info with sck.SendData.
    It sends the contents of the file. The receiving end will need to receive the data and dump it into the file.

    I'm working on a file transfer control for sending multiple files at once complete with MD5 hashing to check for corruption. Should be done soon.

    In the meantime, I would recommend you use CVMichael's example which is also in the CodeBank.

    This was just a code snippet for how to read a file in chunks and basically just send it one chunk at a time (definitely not how I do it anymore ).

    But it will work.

  17. #17
    New Member
    Join Date
    Aug 2009
    Posts
    3

    Re: Visual Basic - Send File With Winsock

    Dear Professionals,
    I need some help here. I'm a new VB beginner, i'm trying to do something like sending files(m2p,jpeg,avi,ppt,txt...) some of the video file might more over than 100mb and i'll develop it by LAN use 1st. any idea for this?
    thanks

  18. #18
    New Member
    Join Date
    Dec 2009
    Posts
    5

    Re: Visual Basic - Send File With Winsock

    I have a question about sending files with a socket and error checking. I'm actually using the old MABRY Socket control and I have a question about error checking when sending a packet. In general, I have my file transfer working but it is only about half as fast as the maximum transfer rate which I see when sending files with FTP.

    I notice that the larger the packets I send the faster it goes. However, I have also noticed that the larger the packet (even only those above 3K sometimes the error rate seems to go up). If I increase it from about 1024 bytes to around 8K it goes faster but for some reason there are errors and I have to resend the packet. So, here's my question and I have a feeling I'm doing this all wrong but here goes:

    1. The Client sends an 8K packet to the server along with a 2 byte checksum attached to the packet that my client program generates.
    2. The server gets the 8K packet and validates it with the checksum
    3. If it's bad the server then sends about 3 bytes or so back to the client telling it to resend the packet. This continues until all the packets are successfully sent.

    Some how I have a feeling I'm just not doing this right. If the server has to wait for the full 8K to arrive then it would seem that during that time the client could be sending another packet and continue sending and sending packets. However, what happens if the packet reaches the server and the data is not what was sent and there is a glitch in one or two or more of the bytes in the packet?

    One other question - with Mabry Socket there's something called Fast Notifications and I'm not sure if this is useful or important to utilize.

    Anyone use the Mabry socket control out there?

    I'm confused.
    Please help.
    Thanks,

  19. #19
    New Member Inuya5ha's Avatar
    Join Date
    Mar 2006
    Location
    AR
    Posts
    7

    Re: Visual Basic - Send File With Winsock

    For some reason, even when waiting for the SendComplete event, files are transferred enterily only over LAN, and not the Internet. When accesing the file via the Internet IP, only the first block of data arrives to destination, no matter how I modify the code... what could be the reason for this?

  20. #20
    New Member
    Join Date
    Dec 2009
    Posts
    5

    Re: Visual Basic - Send File With Winsock

    I got everything figured out before - it was because VFP 6 does not properly handle the ActiveX control and I have found a workaround.

    Inuya5ha - it sounds like the reason you are having trouble is because you cannot just look for data from the socket in a tight loop. You have to wait for the event to fire so that you know data has arrived and then grab it. The SendComplete event will fire again if you wait long enough then more data should arrive.

    Mike

  21. #21
    New Member Inuya5ha's Avatar
    Join Date
    Mar 2006
    Location
    AR
    Posts
    7

    Re: Visual Basic - Send File With Winsock

    Quote Originally Posted by mike1960 View Post
    Inuya5ha - it sounds like the reason you are having trouble is because you cannot just look for data from the socket in a tight loop. You have to wait for the event to fire so that you know data has arrived and then grab it. The SendComplete event will fire again if you wait long enough then more data should arrive.
    Thanks, however I don't handle the receiving of the file, that is done by the users' browser (Firefox or IE). So it definitely must be an error in the code posted here, also notice that it works OK over LAN... should I delay the process somewhere to ensure data is properly sent to the browser?

  22. #22
    Member KJKO's Avatar
    Join Date
    Nov 2012
    Posts
    59

    Re: Visual Basic - Send File With Winsock

    How we do on client side ?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width