2024年4月29日发(作者:)

VB中使用WinSock控件传送文件

传送文件对于网络编程来说是基本的功能,比如远程控制软件。在编制一个软件

时,我从网上下了很多传文件的程序,这些程序提供的传文件功能根本就不能用。

传文本还可以,传二进制文件根本就不行。因此,作为一个基本的功能模块,有

必要单独介绍一下。

首先,在VB中要传送字符串,你可以这样写:

Dim strData As String

strData = "Test"

ta strData

但是如果你传送的二进制文件,你还能用String变量来存放吗?从理论上分析

是不行的,我也做了实验,确实是不行的。文件虽然可以传,但是接受的文件和

发送的不一样,原因可能是二进制文件里可以有任何"字符",但是不是所有的字

符都可以放在String变量里。

除了String类型的变量,VB中其他类型的变量都只有几个字节长,难道一次只

能发几个字节吗?那样岂不是要累死机器了!其实,情况没有那么悲观,我们完

全可以使用数组来解决这个问题,就是使用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 For Binary As #FreeFile '打开文件

DoEvents

LenFile = LOF(FreeF) '获得文件长度

ReDim bytData(1 To LenFile) '根据文件长度重新定义数组大小

Get #FreeF, , bytData '把文件读入到数组里

Close #FreeF '关闭文件

ta bytData '发送数据

End Sub

接受端的程序如下:

Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)

Dim bytData() As Byte

Dim f

f = FreeFile

Open strFileName For Binary As #f

ReDim bytData(1 To bytesTotal)

a 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(FreeFile)中的LOF是获得文件长度的函

数,是VB里带的,我见过很多例子用API,或者循环的读直到末尾来获取文件

长度,这样都是很麻烦的,使用LOF函数就可以了。

这样的程序,即可以传送文本文件,也可以传送二进制文件。但是你有没有发现

这个程序的问题呢?如果我要传送一个50M的文件呢?系统可以为bytData分

配50M的内存空间吗?

于是笔者拿一个50M的文件做实验吧,接收到的文件和原来的文件不一样,比

原来的大。问题出在那呢?

首先,根据文件大小重新定义bytData数组的大小本身就有问题,系统是不可能

无限制的给数组分配空间的,即使可以,也会造成系统响应变慢。在传50M文

件的时候,系统就跟死机了一样。那么怎么解决这个问题呢,一个自然的想法就

是把数据分段传送。程序如下:

发送程序, iPos是个全局变量,初始值为0。这个变量保存着当前数据的位置。

Const iMax = 65535是每个数据块的大小。

dim ipos as long

Const iMax = 65535

Dim FreeF As Integer '空闲的文件号

Dim LenFile As Long '文件的长度

Dim bytData() As Byte '存放数据的数组

FreeF = FreeFile '获得空闲的文件号

Open FileName For Binary As #FreeF '打开文件

DoEvents