VB SOCKET 实现文件传输.docx_第1页
VB SOCKET 实现文件传输.docx_第2页
VB SOCKET 实现文件传输.docx_第3页
VB SOCKET 实现文件传输.docx_第4页
VB SOCKET 实现文件传输.docx_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

VB中使用WinSock控件传送文件 传送文件对于网络编程来说是基本的功能,比如远程控制软件。在编制一个软件时,我从网上下了很多传文件的程序,这些程序提供的传文件功能根本就不能用。传文本还可以,传二进制文件根本就不行。因此,作为一个基本的功能模块,有必要单独介绍一下。 首先,在VB中要传送字符串,你可以这样写: Dim strData As String strData = Test Winsock1.SendData 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 关闭文件 WinS.SendData 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) 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(FreeFile)中的LOF是获得文件长度的函数,是VB里带的,我见过很多例子用API,或者循环的读直到末尾来获取文件长度,这样都是很麻烦的,使用LOF函数就可以了。 这样的程序,即可以传送文本文件,也可以传送二进制文件。但是你有没有发现这个程序的问题呢?如果我要传送一个50M的文件呢?系统可以为bytData分配50M的内存空间吗? 于是笔者拿一个50M的文件做实验吧,接收到的文件和原来的文件不一样,比原来的大。问题出在那呢? 首先,根据文件大小重新定义bytData数组的大小本身就有问题,系统是不可能无限制的给数组分配空间的,即使可以,也会造成系统响应变慢。在传50M文件的时候,系统就跟死机了一样。那么怎么解决这个问题呢,一个自然的想法就是把数据分段传送。程序如下: 发送程序, iPos是个全局变量,初始值为0。这个变量保存着当前数据的位置。Const iMax = 65535是每个数据块的大小。 dim ipos as longConst iMax = 65535Dim FreeF As Integer 空闲的文件号 Dim LenFile As Long 文件的长度 Dim bytData() As Byte 存放数据的数组 FreeF = FreeFile 获得空闲的文件号 Open FileName For Binary As #FreeF 打开文件 DoEvents LenFile = LOF(FreeF) 获得文件长度 If LenFile = (LenFile - iMax) 发送整块数据的循环 ReDim bytData(1 To iMax) Get #FreeF, iPos + 1, bytData 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 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, bytData 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 数据缓冲区,文件包数,已传输的数据Private alreadySend As BooleanPrivate cmsStr As StringConst fileD As String = D:NMSPluginsourceLanBus.rarPrivate Sub cmdConnectClient_Click() WinsockSend.Close WinsockSend.Protocol = sckTCPProtocol WinsockSend.RemoteHost = WinsockSend.RemotePort = 8080 WinsockSend.Connect 连接客户端End SubPrivate Sub cmdSendFile_Click() Open fileD For Binary As #3 filename = LanBus.rar filelength = LOF(3) Close #3 WinsockSend.SendData (NMSP_AYUREADY)End SubPrivate Sub WinsockSend_Connect() StatusBar1.Caption = 已与客户端建立连接。End Sub发送文件按钮事件代码:Private Sub sendFile() Dim i As Integer Dim j As Long Dim m As Long filepath = fileD StatusBar1.Caption = 向客户端传送文件: & filename & 大小为: & filelength 计算需要传输文件的包数 pack = (filelength - sendedData) PACKSIZE If (filelength - sendedData) Mod PACKSIZE) 0 Then pack = pack + 1 End If If pack = 0 Then pack = pack + 1 End If 传输文件 Open filepath For Binary As #1 For i = 1 To pack 如果只有一包 If pack = 1 Then Debug.Print filename= & filename & | filelength= & filelength & | 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 读取最后一包的数据 ReDim data(filelength - sendedData) For j = 1 To filelength - sendedData Get #1, sendedData + j, data(j) Next 发送文件数据 WinsockSend.SendData data 更新已传输文件的数据 sendedData = filelength Exit For Else 将文件数据放到数据缓冲区 ReDim data(PACKSIZE) For m = 1 To PACKSIZE Get #1, sendedData + m, data(j) Next 发送文件数据 WinsockSend.SendData data 更新已传输文件的数据 sendedData = sendedData + PACKSIZE End If ProgressBar1.Value = Int(sendedData / filelength) * 100) Next ProgressBar1.Value = Int(sendedData / filelength) * 100) Close #1 alreadySend = False End Sub客户端反馈Private Sub WinsockSend_DataArrival(ByVal bytesTotal As Long) Dim cmdStr As String WinsockSend.GetData cmdStr, vbString Debug.Print cmdStr If Mid(cmdStr, 1, 13) = NMSP_IAMREADY Then 客户端已准备好接收时,要求客户端报告已经接收的文件大小 WinsockSend.SendData NMSP_RPTCURLE & filename ElseIf Mid(cmdStr, 1, 13) = NMSP_REQFILEN Then 客户端要求发送文件名称 WinsockSend.SendData NMSP_FILENAME= & filename ElseIf Mid(cmdStr, 1, 13) = NMSP_REQFILES Then 客户端要求发送文件大小 WinsockSend.SendData NMSP_FILESIZE= & filelength WinsockSend.GetData send, vbLong ElseIf Mid(cmdStr, 1, 13) = NMSP_RECEIVED Then 收到客户端已经接收到的文件大小报告 Debug.Print 客户端已经接收了 & Mid(cmdStr, 14, Len(cmdStr) sendedData = Mid(cmdStr, 15, Len(cmdStr) If filelength = sendedData Then WinsockSend.SendData NMSP_SENDDONE 初始化文件名,大小,已接收大小,遍历是否还需要向别的客户端发送 Let filename = Let filelength = 0 Let sendedData = 0 WinsockSend.Close StatusBar1.Caption = 文件发送完毕! Else Call sendFile End If End IfEnd Sub= 客户端 =Option ExplicitDim flag As Boolean 设置是否继续接收文件的开关标识Private readyReceive As BooleanPrivate filename As StringPrivate tempfile As StringPrivate realfile As StringPrivate reveivePath As StringPrivate filelength As Long 存储文件信息Private data() As Byte, received As Long 声明数据缓冲区和已接收的数据Private Sub Form_Load() reveivePath = App.Path & received WinsockReceive.Protocol = sckTCPProtocol WinsockReceive.LocalPort = 8080 WinsockReceive.Listen Call initReceiveStateEnd SubPrivate Sub WinsockReceive_Connect() StatusBar1.Caption = 已经连接到服务器End SubPrivate Sub WinsockReceive_ConnectionRequest(ByVal requestID As Long) If WinsockReceive.State 0 Then WinsockReceive.Close End If WinsockReceive.Accept requestID StatusBar1.Caption = 已接受连接请求。End SubPrivate Sub WinsockReceive_DataArrival(ByVal bytesTotal As Long) Dim j As Long 分别接收传输文件的文件名、文件长度 WinsockReceive.GetData filename, vbString, bytesTotal - 4 WinsockReceive.GetData filelength, vbLong 判断指令类型 If readyReceive = False Then Dim cmdStr As String WinsockReceive.GetData cmdStr, vbString Debug.Print cmdStr If Mid(cmdStr, 1, 13) = NMSP_AYUREADY Then 询问是否准备好接收文件 If filename = Then WinsockReceive.SendData (NMSP_REQFILEN) ElseIf filelength = 0 Then WinsockReceive.SendData (NMSP_REQFILES) Else WinsockReceive.SendData (NMSP_IAMREADY) End If ElseIf Mid(cmdStr, 1, 13) = NMSP_FILENAME Then 文件名 filename = Mid(cmdStr, 15, Len(cmdStr) WinsockReceive.SendData (NMSP_REQFILES) ElseIf Mid(cmdStr, 1, 13) = NMSP_FILESIZE Then 文件大小 filelength = Mid(cmdStr, 15, Len(cmdStr) Debug.Print filelength If (filelength 0) ThenWinsockReceive.SendData (NMSP_IAMREADY) End If ElseIf Mid(cmdStr, 1, 13) = NMSP_RPTCURLE Then 服务器端要求提供已经接收的文件大小 为传输文件设置临时文件 realfile = reveivePath & filename tempfile = reveivePath & filename & .td 返回已接收的数据 Open realfile For Binary As #1 Open tempfile For Binary As #2 If LOF(2) 0 Then Input #2, received Debug.Print received= & received End If Close #2 WinsockReceive.SendData NMSP_RECEIVED= & received readyReceive = True StatusBar1.Caption = 准备接收文件: & filename & 大小为: & filelength ElseIf Mid(cmdStr, 1, 14) = NMSP_SENDDONE= Then 服务器发送文件完毕 执行 安装操作 End If Else realfile = reveive

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论