VB SOCKET 实现文件传输.docx

上传人:b****6 文档编号:3080309 上传时间:2022-11-17 格式:DOCX 页数:13 大小:19.53KB
下载 相关 举报
VB SOCKET 实现文件传输.docx_第1页
第1页 / 共13页
VB SOCKET 实现文件传输.docx_第2页
第2页 / 共13页
VB SOCKET 实现文件传输.docx_第3页
第3页 / 共13页
VB SOCKET 实现文件传输.docx_第4页
第4页 / 共13页
VB SOCKET 实现文件传输.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

VB SOCKET 实现文件传输.docx

《VB SOCKET 实现文件传输.docx》由会员分享,可在线阅读,更多相关《VB SOCKET 实现文件传输.docx(13页珍藏版)》请在冰豆网上搜索。

VB SOCKET 实现文件传输.docx

VBSOCKET实现文件传输

VB中使用WinSock控件传送文件

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

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

传文本还可以,传二进制文件根本就不行。

因此,作为一个基本的功能模块,有必要单独介绍一下。

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

DimstrDataAsString

strData="Test"

Winsock1.SendDatastrData

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

从理论上分析是不行的,我也做了实验,确实是不行的。

文件虽然可以传,但是接受的文件和发送的不一样,原因可能是二进制文件里可以有任何"字符",但是不是所有的字符都可以放在String变量里。

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

那样岂不是要累死机器了!

其实,情况没有那么悲观,我们完全可以使用数组来解决这个问题,就是使用byte数组。

把要传送的文件都读到数组里,然后发送出去。

程序如下:

FileName为要传送的文件名,WinS为发送文件的WinSock控件。

这是一个发送端的程序。

PublicSubSendFile(FileNameAsString,WinSAsWinsock)

DimFreeFAsInteger'空闲的文件号

DimLenFileAsLong'文件的长度

DimbytData()AsByte'存放数据的数组

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

OpenFileNameForBinaryAs#FreeFile'打开文件

DoEvents

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

ReDimbytData(1ToLenFile)'根据文件长度重新定义数组大小

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

Close#FreeF'关闭文件

WinS.SendDatabytData'发送数据

EndSub

接受端的程序如下:

PrivateSubWinsock1_DataArrival(ByValbytesTotalAsLong)

DimbytData()AsByte

Dimf

f=FreeFile

OpenstrFileNameForBinaryAs#f

ReDimbytData(1TobytesTotal)

Winsock1.GetDatabytData

Put#f,i,bytData

i=i+bytesTotal'保证每次写都是在文件的末尾,i是个全局变量

Close#f

EndSub

这里有两个需要注意的地方,ReDimPreservebytData(1ToLenFile),下标是从1开始的,如果你写成ReDimbytData(LenFile),下标就是从0开始了,数组就有LenFile+1长了。

LenFile=LOF(FreeFile)中的LOF是获得文件长度的函数,是VB里带的,我见过很多例子用API,或者循环的读直到末尾来获取文件长度,这样都是很麻烦的,使用LOF函数就可以了。

这样的程序,即可以传送文本文件,也可以传送二进制文件。

但是你有没有发现这个程序的问题呢?

如果我要传送一个50M的文件呢?

系统可以为bytData分配50M的内存空间吗?

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

问题出在那呢?

首先,根据文件大小重新定义bytData数组的大小本身就有问题,系统是不可能无限制的给数组分配空间的,即使可以,也会造成系统响应变慢。

在传50M文件的时候,系统就跟死机了一样。

那么怎么解决这个问题呢,一个自然的想法就是把数据分段传送。

程序如下:

发送程序,iPos是个全局变量,初始值为0。

这个变量保存着当前数据的位置。

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

dimiposaslong

ConstiMax=65535

DimFreeFAsInteger'空闲的文件号

DimLenFileAsLong'文件的长度

DimbytData()AsByte'存放数据的数组

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

OpenFileNameForBinaryAs#FreeF'打开文件

DoEvents

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

IfLenFile<=iMaxThen'如果要发送的文件小于数据块大小,直接发送

ReDimbytData(1ToLenFile)'根据文件长度重新定义数组大小

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

Close#FreeF'关闭文件

WinS.SendDatabytData'发送数据

ExitSub

EndIf

'文件大于数据块大小,进行分块发送

DoUntil(iPos>=(LenFile-iMax))'发送整块数据的循环

ReDimbytData(1ToiMax)

Get#FreeF,iPos+1,bytData

WinS.SendDatabytData

iPos=iPos+iMax'移动iPos,使它指向下来要读的数据

Loop

'这里要注意的是,必须检查文件有没有剩下的数据,如果文件大小正好等于数据块大小的

'整数倍,那么就没有剩下的数据了

ReDimbytData(1ToLenFile-iPos)'发送剩下的不够一个数据块的数据

Get#FreeF,iPos+1,bytData

WinS.SendDatabytData

Close#FreeF

下面是接收端的程序:

PrivateSubWinsock1_DataArrival(ByValbytesTotalAsLong)

DimbytData()AsByte

DimlLenFileAsLong

Dimf

f=FreeFile

OpenstrFileNameForBinaryAs#f'strFileName是文件名

lLenFile=LOF(f)

ReDimbytData(1TobytesTotal)

Winsock1.GetDatabytData

IflLenFile=0Then'lLenFile=0表示是第一次打开文件,这里有个问题,就是'如果如果该文件存在的话,就会出错,应该在打开前检查文件是否存在。

(这里我省略了)

Put#f,1,bytData

Else

Put#f,lLenFile+1,bytData

EndIf

Close#f

EndSub

 

VBSOCKET实现文件传输支持断点续传

OptionExplicit

ConstPACKSIZEAsLong=65536'每包大小为64K

PrivatefilepathAsString

PrivatefilenameAsString

PrivatefilelengthAsLong'存储文件信息

Privatedata()AsByte

PrivatepackAsLong

PrivatesendedDataAsLong'数据缓冲区,文件包数,已传输的数据

PrivatealreadySendAsBoolean

PrivatecmsStrAsString

ConstfileDAsString="D:

\NMSPlugin\source\LanBus.rar"

 

PrivateSubcmdConnectClient_Click()

WinsockSend.Close

WinsockSend.Protocol=sckTCPProtocol

WinsockSend.RemoteHost="127.0.0.1"

WinsockSend.RemotePort=8080

WinsockSend.Connect'连接客户端

EndSub

PrivateSubcmdSendFile_Click()

OpenfileDForBinaryAs#3

filename="LanBus.rar"

filelength=LOF(3)

Close#3

WinsockSend.SendData("NMSP_AYUREADY")

EndSub

PrivateSubWinsockSend_Connect()

StatusBar1.Caption="已与客户端建立连接。

"

EndSub

'"发送文件"按钮事件代码:

PrivateSubsendFile()

DimiAsInteger

DimjAsLong

DimmAsLong

filepath=fileD

StatusBar1.Caption="向客户端传送文件:

"&filename&"大小为:

"&filelength

'计算需要传输文件的包数

pack=(filelength-sendedData)\PACKSIZE

If((filelength-sendedData)ModPACKSIZE)<>0Then

pack=pack+1

EndIf

Ifpack=0Then

pack=pack+1

EndIf

'传输文件

OpenfilepathForBinaryAs#1

Fori=1Topack

'如果只有一包

Ifpack=1Then

Debug.Print"filename="&filename&"|filelength="&filelength&"|send="&sendedData

ReDimdata(filelength-sendedData)

'读取数据

Forj=sendedData+1Tofilelength

Get#1,j,data(j-sendedData)

Next

'更新已传输文件的数据

sendedData=filelength

'发送文件数据

WinsockSend.SendDatadata

'如果是最后一包

ElseIfi+1=packThen

'读取最后一包的数据

ReDimdata(filelength-sendedData)

Forj=1Tofilelength-sendedData

Get#1,sendedData+j,data(j)

Next

'发送文件数据

WinsockSend.SendDatadata

'更新已传输文件的数据

sendedData=fil

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 调解书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1