利用Winsock下载文件(支持断点续传)

第一步,建立工程,引用Winsock(Visual Basic最好打SP6,否则MS有一个Bug),在此省略

第二步,具体实现代码步骤1:发送请求
说明:
(1)这里简单采用了判断是否已经有同名文件表示是否要断点续传
(2)下载的地址,大小和已下载字节数也只是简单地存在ini文件中,更安全的做法本文不作讨论
有兴趣的朋友可以联系我

'--------------------------------------------------------------------------------
'   Name:DownloadFile
'   Author:Reker 2004/3/20
'   Desc:连接远端主机,发送接收文件请求,等待远端主机响应
'   Params:None
'   History:None
'--------------------------------------------------------------------------------
Private Sub DownloadFile()
    On Error Resume Next
    StartTime = Time()
    With WinSck
        .RemoteHost = Host '远端主机地址
        .RemotePort = 80
        .Connect
        '等待服务器连接相应
        Do While .State <> sckConnected
            DoEvents: DoEvents: DoEvents: DoEvents
            '20秒超时
            If DateDiff("s", StartTime, Time()) > 20 Then
                ShowInfo "连接超时"
                .Close
                Exit Sub
            End If
        Loop
        '发送下载文件请求
        '此处使用HTTP/1.0协议
        strCommand = "GET " + UpdateURL + " HTTP/1.0" + vbCrLf '下载地址
        strCommand = strCommand + "Accept: */*" + vbCrLf      '这句可以不要
        strCommand = strCommand + "Accept: text/html" + vbCrLf '这句可以不要
        strCommand = strCommand + vbCrLf
        strCommand = strCommand & "Host: " & Host & vbCrLf
        If Dir(SaveFileName) <> "" Then '是否已经存在下载文件
            Dim confirm
            confirm = MsgBox("已经存在文件,是否断点续传?", vbYesNo + vbQuestion, "提示")
            If confirm = vbYes Then
                DownPosition = ""
                If Not oFileCtrl.ReadKeyFromIni("Update", "DownSize", AppPath + "Update.ini", DownPosition) Then
                '读取上次下载的字节数
                    MsgBox "读取大小错误", vbInformation, "提示"
                End If
                '发送断点续传请求
                strCommand = strCommand & "Range: bytes=" & CLng(DownPosition) & "-" & vbCrLf
            Else
                Kill SaveFileName '删除原文件
            End If
        End If
        strCommand = strCommand & "Connection: Keep-Alive" & vbCrLf
        strCommand = strCommand & vbCrLf
        .SendData strCommand
    End With
    If Err Then
        lblProcessResult.Caption = lblProcessResult.Caption & vbCrLf & vbCrLf & "下载文件出错:" & Err.Description
        lblProcessResult.Refresh
    End If
End Sub


第二步,具体实现代码步骤2:接收数据
'--------------------------------------------------------------------------------
'   Name:Winsck_DataArrival
'   Author:Reker 2004/3/20
'   Desc:略
'   Params:略
'   Return:None
'   History:None
'--------------------------------------------------------------------------------
Private Sub Winsck_DataArrival(ByVal bytesTotal As Long)
    On Error Resume Next
    'DoEvents: DoEvents
    Dim ByteData() As Byte
    WinSck.GetData ByteData(), vbByte
    ReceiveData = ReceiveData & StrConv(ByteData(), vbUnicode)
    If InStr(1, ReceiveData, "Content-Length:") > 0 And FileSize = 0 Then '仅第一次计算,FileSize=0
        Dim pos1 As Long, pos2 As Long
        pos1 = InStr(1, ReceiveData, "Content-Length:")
        pos2 = InStr(pos1 + 16, ReceiveData, vbCrLf)
        If pos2 > pos1 Then
            FileSizeByte = Mid(ReceiveData, pos1 + 16, pos2 - pos1 - 16) '计算文件的长度
            StartTime = Timer() '保存开始下载的时间
            ProgssBar.Max = FileSizeByte '设置进度条
            FileSize = FormatNumber(FileSizeByte / 1024, 2) '以KB表示
            ShowInfo "本次下载的文件共" + CStr(FileSize) + "KB..."
        End If
    End If
    '从服务器响应返回的数据查找下载文件的起始位置
    If FileHeaderLen = 0 Then
        For i = 0 To UBound(ByteData()) - 3
            If ByteData(i) = 13 And ByteData(i + 1) = 10 And ByteData(i + 2) = 13 And ByteData(i + 3) = 10 Then
                StartPos = i + 4 '将文件头的长度保存下来
                FileHeaderLen = StartPos
                Exit For
            End If
            'DoEvents 
        Next i
    End If
    FileSizeHaveDown = bytesTotal + FileSizeHaveDown - FileHeaderLen     
    '已下载文件长度,需减去响应的文件头长度
    dblDownloadSpeed = FormatNumber(FormatNumber(FileSizeHaveDown / 1024, 2) / (FormatNumber((Timer() - StartTime), 4)), 2)  '计算下载速率 KB/S
    If dblDownloadSpeed <> 0 Then  '计算剩余下载的时间
        sRestTime = GetRestTime(CLng((FileSize - (FileSizeHaveDown) / 1024) / dblDownloadSpeed)) '此过程略,可以删除此段代码
        labRestTime.Caption = "剩余时间:º" + sRestTime
        labRestTime.Refresh
    End If
    labDownloadSpeed.Caption = CStr(dblDownloadSpeed) + " kb/s"
    labDownloadSpeed.Refresh
    ProgssBar.Value = FileSizeHaveDown
    '写数据
    Fnum = FreeFile()
    Open SaveFileName For Binary Lock Write As #Fnum
    If LOF(Fnum) > 0 Then
        Seek #Fnum, LOF(Fnum) + 1
    End If
    If StartPos > 0 Then
        For i = StartPos To UBound(ByteData())
            Put #Fnum, , ByteData(i)
        Next i
    Else 
        Put #Fnum, , ByteData()
    End If
    Close #Fnum 
    If Err Then
        lblProcessResult.Caption = lblProcessResult.Caption & vbCrLf & 获取数据出错:" & Err.Description
        lblProcessResult.Refresh
    End If
End Sub
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
一、WinSock简介 Socket(套接字)最初是由加利福尼亚大学Berkeley(伯克利)分校为UNIX操作系统开发的网络通信接口,随着UNIX的广泛使用,Socket成为当前最流行的网络通信应用程序接口之一。20世纪90年代初,由Sun Microsystems,JSB,FTP software,Microdyne和Microsoft等几家公司共同定制了一套标准,即Windows Socket规范,简称WinSock。 VB编写网络程序主要有两种方式:1.winsock控件 2.winsockAPI 二、WinSock控件的使用 1.WinSock控件的主要属性 LocalHostName属性 本地机器名 LocalIP属性 本地机器IP地址 LocalPort属性 本地机器通信程序的端口(0<端口<65536) RemoteHost属性 远程机器名 RemotePort属性 远程机器的通信程序端口 Protocol属性 通过Protocol属性可以设置WinSock控件连接远程计算机使用的协议。可选的协议是TCP和UDP对应的VB的常量分别是sckTCPProtocol和sckUDPProtocol,Winsock控件默认协议是TCP。注意:虽然可以在运行时设置协议,但必须在连接未建立或断开连接后。 SocketHandle属性 返回当前socket连接的句柄,这是只读属性。 RemoteHostIP属性 属性返回远程计算机的IP地址。在客户端,当使用了控件的Connect方法后,远程计算机的IP地址就赋给了RemoteHostIP属性,而在服务器端,当ConnectRequest事件后,远程计算机(客户端)的IP地址就赋给了这个属性。如果使用的是UDP协议那么当DataArrival事件后,发送UDP报文的计算机的IP才赋给了这个属性。 ByteReceived属性 返回当前接收缓冲区中的字节数 State属性 返回WinSock控件当前的状态 常数 值 描述 sckClosed 0 缺省值,关闭。 SckOpen 1 打开。 SckListening 2 侦听 sckConnectionPending 3 连接挂起 sckResolvingHost 4 识别主机。 sckHostResolved 5 已识别主机 sckConnecting 6 正在连接。 sckConnected 7 已连接。 sckClosing 8 同级人员正在关闭连接。 sckError 9   错误 2.WinSock主要方法 Listen方法 方法用于服务器程序,等待客户访问。格式:Winsock对象.listen Connect方法 用于向远程主机发出连接请求。格式:Winsock对象.connect [远程主机IP,远程端口] Accept方法 用于接受一个连接请求。格式:Winsock对象.accept Request ID Senddata方法 用于发送数据。格式:Winsock对象.senddata 数据 Getdata方法 用来取得接收到的数据。格式:Winsock对象.getdata 变量 [,数据类型 [,最大长度]] Close方法 关闭当前连接。格式:Winsock对象.close Bind方法 用Bind方法可以把一个端口号固定为本控件使用,使得别的应用程序不能再使用这个端口。 Listen方法Listen方法只在使用TCP协议时有用。它将应用程序置于监听检测状态。 Connect方法 当本地计算机希望和远程计算机建立连接时,就可以调用Connect方法。Connect方法调用的规范为:Connect RemoteHost,RemotePort Accept方法 当服务器接收到客户端的连接请求后,服务器有权决定是否接受客户端的请求。 SendData方法当连接建立后,要发送数据就可以调用SendData方法,该方法只有一个参数,就是要发送的数据。 GetData方法 当本地计算机接收到远程计算机的数据时,数据存放在缓冲区中,要从缓冲区中取出数据,可以使用GetData方法。GetData方法调用规范如下:GetData
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值