-
Apr 2nd, 2005, 04:10 PM
#1
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
-
Apr 2nd, 2005, 11:59 PM
#2
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...
-
Apr 3rd, 2005, 12:31 AM
#3
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:
Option Explicit
Private iFileNum As Integer, lPacketSize As Long
Public Sub SendFile(SocketObject As Winsock, ByVal FilePath As String, Optional ByVal PacketSize As Long = 1024)
Dim Buffer() As Byte
lPacketSize = PacketSize ' save the PacketSize for the timer
Timer1.Enabled = False ' make suze timer is not enabled
iFileNum = FreeFile ' get free file number
Open FilePath For Binary Access Read As iFileNum ' open file
' if file size is smaller than PacketSize, then send the whole file, but not more
ReDim Buffer(lngMIN(LOF(iFileNum), PacketSize) - 1)
Get iFileNum, , Buffer ' read data
SocketObject.SendData Buffer ' send data
End Sub
Public Function lngMIN(ByVal L1 As Long, ByVal L2 As Long) As Long
If L1 < L2 Then
lngMIN = L1
Else
lngMIN = L2
End If
End Function
Private Sub Timer1_Timer()
Dim Buffer() As Byte, BuffSize As Long
Timer1.Enabled = False
If iFileNum <= 0 Then Exit Sub
If Loc(iFileNum) >= LOF(iFileNum) Then ' FILE COMPLETE
Close iFileNum ' close file
iFileNum = 0 ' set file number to 0, timer will exit if another timer event
Exit Sub
End If
'if the remaining size in the file is smaller then PacketSize, the read only whatever is left
BuffSize = lngMIN(LOF(iFileNum) - Loc(iFileNum), lPacketSize)
ReDim Buffer(BuffSize - 1) ' resize buffer
Get iFileNum, , Buffer ' read data
SocketObject.SendData Buffer ' send data
' Show progress
Me.Caption = Format(Loc(iFileNum) / CDbl(LOF(iFileNum)) * 100#, "#0.00") & "% Done"
' timer event will be called again when last packet is sent, close the file then
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
' read incomming data here...
End Sub
Private Sub Winsock1_SendComplete()
' can't call SendData here, so enable timer to do it...
Timer1.Enabled = False
Timer1.Interval = 1
Timer1.Enabled = True
End Sub
-
Apr 3rd, 2005, 05:53 AM
#4
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.
-
Nov 29th, 2005, 10:01 AM
#5
New Member
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
-
Nov 29th, 2005, 11:39 AM
#6
Re: Visual Basic - Send File With Winsock
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 ?
-
Oct 4th, 2006, 11:06 AM
#7
New Member
Re: Visual Basic - Send File With Winsock
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.
-
Oct 4th, 2006, 11:24 AM
#8
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
-
Oct 4th, 2006, 11:57 AM
#9
New Member
Re: Visual Basic - Send File With Winsock
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?
-
Oct 5th, 2006, 07:44 AM
#10
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.
-
Oct 5th, 2006, 07:50 AM
#11
Re: Visual Basic - Send File With Winsock
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.
-
Jul 17th, 2007, 11:23 AM
#12
New Member
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)
?
-
Jul 17th, 2007, 11:49 AM
#13
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...
-
Jul 17th, 2007, 12:08 PM
#14
New Member
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
-
Aug 5th, 2007, 05:32 AM
#15
New Member
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.
-
Aug 5th, 2007, 06:00 PM
#16
Re: Visual Basic - Send File With Winsock
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.
-
Aug 25th, 2009, 09:31 PM
#17
New Member
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
-
Dec 24th, 2009, 05:48 PM
#18
New Member
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,
-
Oct 11th, 2010, 12:19 PM
#19
New Member
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?
-
Oct 11th, 2010, 12:30 PM
#20
New Member
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
-
Oct 12th, 2010, 11:45 AM
#21
New Member
Re: Visual Basic - Send File With Winsock
Originally Posted by mike1960
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?
-
Nov 22nd, 2012, 05:40 PM
#22
Member
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|