1、其实,情况没有那么悲观,我们完全可以使用数组来解决这个问题,就是使用byte数组。把要传送的文件都读到数组里,然后发送出去。程序如下: FileName 为要传送的文件名,WinS为发送文件的WinSock控件。这是一个发送端的程序。 Public Sub SendFile(FileName As String, WinS As Winsock) Dim FreeF As Integer 空闲的文件号 Dim LenFile As Long 文件的长度 Dim bytData() As Byte 存放数据的数组 FreeF = FreeFile 获得空闲的文件号 Open FileName F
2、or Binary As #FreeFile 打开文件 DoEvents LenFile = LOF(FreeF) 获得文件长度 ReDim bytData(1 To LenFile) 根据文件长度重新定义数组大小 Get #FreeF, , bytData 把文件读入到数组里 Close #FreeF 关闭文件 WinS.SendData bytData 发送数据 End Sub 承受端的程序如下: Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long) Dim bytData() As Byte Dim f f = FreeFi
3、le Open strFileName For Binary As #f ReDim bytData(1 To bytesTotal) Winsock1.GetData bytData Put #f, i, bytData i = i + bytesTotal 保证每次写都是在文件的末尾, i是个全局变量 Close #f End Sub 这里有两个需要注意的地方,ReDim Preserve bytData(1 To LenFile),下标是从1开始的,如果你写成ReDim bytData( LenFile),下标就是从0开始了,数组就有LenFile+1长了。LenFile = LOF(F
4、reeFile)中的LOF是获得文件长度的函数,是VB里带的,我见过很多例子用API,或者循环的读直到末尾来获取文件长度,这样都是很麻烦的,使用LOF函数就可以了。 这样的程序,即可以传送文本文件,也可以传送二进制文件。但是你有没有发现这个程序的问题呢?如果我要传送一个50M的文件呢?系统可以为bytData分配50M的内存空间吗? 于是笔者拿一个50M的文件做实验吧,接收到的文件和原来的文件不一样,比原来的大。问题出在那呢? 首先,根据文件大小重新定义bytData数组的大小本身就有问题,系统是不可能无限制的给数组分配空间的,即使可以,也会造成系统响应变慢。在传50M文件的时候,系统就跟死机
5、了一样。那么怎么解决这个问题呢,一个自然的想法就是把数据分段传送。 发送程序, iPos是个全局变量,初始值为0。这个变量保存着当前数据的位置。Const iMax = 65535是每个数据块的大小。 dim ipos as longConst iMax = 65535Dim FreeF As Integer 获得空闲的文件号 Open FileName For Binary As #FreeF 获得文件长度 If LenFile = (LenFile - iMax) 发送整块数据的循环 ReDim bytData(1 To iMax) Get #FreeF, iPos + 1, bytDat
6、a WinS.SendData bytData iPos = iPos + iMax 移动iPos,使它指向下来要读的数据 Loop 这里要注意的是,必须检查文件有没有剩下的数据,如果文件大小正好等于数据块大小的 整数倍,那么就没有剩下的数据了 ReDim bytData(1 To LenFile - iPos) 发送剩下的不够一个数据块的数据 Get #FreeF, iPos + 1, bytData WinS.SendData bytData Close #FreeF 下面是接收端的程序: Private Sub Winsock1_DataArrival(ByVal bytesTotal
7、As Long) Dim bytData() As Byte Dim lLenFile As Long Dim f f = FreeFile Open strFileName For Binary As #f strFileName是文件名 lLenFile = LOF(f) ReDim bytData(1 To bytesTotal) Winsock1.GetData bytData If lLenFile = 0 Then lLenFile=0表示是第一次打开文件,这里有个问题,就是如果如果该文件存在的话,就会出错,应该在打开前检查文件是否存在。这里我省略了 Put #f, 1, bytD
8、ata Else Put #f, lLenFile + 1, bytData End If Close #f End SubVB SOCKET 实现文件传输 支持断点续传Option ExplicitConst PACKSIZE As Long = 65536 每包大小为64KPrivate filepath As StringPrivate filename As StringPrivate filelength As Long 存储文件信息Private data() As BytePrivate pack As LongPrivate sendedData As Long 数据缓冲区,文
9、件包数,已传输的数据Private alreadySend As BooleanPrivate cmsStr As StringConst fileD As String = D:NMSPluginsourceLanBus.rarPrivate Sub cmdConnectClient_Click() WinsockSend.Protocol = sckTCPProtocol WinsockSend.RemoteHost = 127.0.0.1 WinsockSend.RemotePort = 8080 WinsockSend.Connect 连接客户端End SubPrivate Sub c
10、mdSendFile_Click() Open fileD For Binary As #3 filename = LanBus.rar filelength = LOF(3) Close #3 WinsockSend.SendData (NMSP_AYUREADY)Private Sub WinsockSend_Connect() StatusBar1.Caption = 已与客户端建立连接。发送文件按钮事件代码:Private Sub sendFile() Dim i As Integer Dim j As Long Dim m As Long filepath = fileD向客户端传送
11、文件: & filename & 大小为: filelength 计算需要传输文件的包数 pack = (filelength - sendedData) PACKSIZE If (filelength - sendedData) Mod PACKSIZE) 0 Then pack = pack + 1 End If If pack = 0 Then传输文件 Open filepath For Binary As #1 For i = 1 To pack如果只有一包 If pack = 1 Then Debug.Print filename= | filelength= filelength
12、& | send= sendedData ReDim data(filelength - sendedData)读取数据 For j = sendedData + 1 To filelength Get #1, j, data(j - sendedData) Next更新已传输文件的数据 sendedData = filelength发送文件数据 WinsockSend.SendData data如果是最后一包 ElseIf i + 1 = pack Then读取最后一包的数据 For j = 1 To filelength - sendedData Get #1, sendedData + j, data(j) Exit For Else将文件数据放到数据缓冲区 ReDim data(PACKSIZE) For m = 1 To PACKSIZE Get #1, sendedData + m, data(j) sendedData = sendedData + PACKSIZE End