小弟遇到一问题,在winsock1_DataArrival事件中,我写入了以下代码,,.     Winsock1.GetData DATA, vbString     '得到数据     Dim Pos%, LENGTH%, HEAD$
     Pos = InStr(DATA, vbCrLf & vbCrLf)  '得到头结束的位置
     LENGTH = Len(DATA)                  '整个数据的长度
     HEAD = Left(DATA, Pos - 1)          '得到头的字符串
     DATA = Right(DATA, LENGTH - Pos - 3)  '除掉头外的剩下数据段        
     BytesRemaining = 507558               '通过其他方法得到的文件实际大小'-----------开始写数据到文件--------
    If BytesAlreadySent < BytesRemaining + 1 Then 
        '------BytesAlreadySent表示在本地下载文件的写入点
        Open FilePathName For Binary Access Write As #1  
        '------FilePathName 为本地存放的地址与文件名的变量(如:c:\t.exe)
        Put #1, BytesAlreadySent, DATA 
        BytesAlreadySent = BytesAlreadySent + bytesTotal
        Close #1
    End If
 '-----------------------------------以上的程序预想现实文件的下载操作,但实际情况却是:下载下来的文件比实际大了一百多个字节。或十一个字节,或小一百多个字节。
请各位大侠帮帮小弟我的忙!!!谢了先

解决方案 »

  1.   

    超快速的多文件传送源码,在本地局域网上可达到1.8Mb+的速度
    http://www.21code.com/codebase/?pos=down&id=1920
      

  2.   

    今晚刚解决这个问题,
    你的代码问题在于你传输时是用字符串传输,应该使用Byte数组类型传输
    在网络传输中都是使用ANSI传输的
    所以你的头上的两行可以这样写
    dim Bt_RecieveByte() as byte
    Winsock1.GetData Bt_RecieveByte(), vbbyte
    然后直接将其写入以二进制方式打开的文件中
      

  3.   

    我用字符串打开的原因是想得到原始文件的大小。头里有如下信息:
    --------------------------------------------
    HTTP/1.1 200 OK
    Date: Wed, 07 Jan 2004 23:54:34 GMT
    Server: Apache/1.3.22 (Unix)  (Red-Hat/Linux) mod_ssl/2.8.12 OpenSSL/0.9.6b DAV/1.0.3 PHP/4.1.2 mod_perl/1.26
    Last-Modified: Sun, 04 Jan 2004 06:46:00 GMT
    ETag: "540c9-7bea6-3ff7b6a8"
    Accept-Ranges: bytes
    Content-Length: 507558
    Connection: close
    Content-Type: text/plain--------------------------------------------
    而Content-Length: 507558就是原始文件的大小,如果用byte方式,就不能得到该信息,请问我还能通过其他方式得到原始文件的大小吗?
      

  4.   

    如果服务器端是你自己写的,你可以通过两次传输实现
    即第一次传输字符串,第二次传输Byte数据
    如果是别人的服务端
    那你只有可以用Byte数组接受
    然后写一个Byte转字符串的数据,得到文件大小,再接受其他Byte数据写入文件
    转字符串可以这样写
    dim Bt_RecieveByte() as byte
    dim i as integer
    Static StrHeader as string
    Winsock1.GetData Bt_RecieveByte(), vbbyte
    do while instr(1,Strheader, "Content-Type")  Strheader=Strheader+cstr(Bt_RecieveByte(i))
      i=i+1 loop当找到"Content-Type"字符串以后,你就可以再Strheader字符串中找到文件大小了
      

  5.   

    修正一下
    是do while not instr(1,Strheader, "Content-Type")代码没做测试,只是说明思路,你自己再看看吧
      

  6.   

    我现在把函数改为了数组的方式,但得到的文件仍比以前的大了350个字节
    ----------------------------------------------------------------------
    Private Sub winsock1_DataArrival(ByVal bytesTotal As Long)
        Dim bytData() As Byte
        ReDim bytData(bytesTotal)        Winsock1.GetData bytData, vbByte
        
            Open FilePathName For Binary As #1   'opens file for output
            Put #1, BytesAlreadySent, bytData 'writes data to the end of file
            BytesAlreadySent = BytesAlreadySent + bytesTotal
            Close #1
    End Sub'------------------------------------------------------------------------------我只有一个客户端,没有服务器端,就是一个直接从服务器中相应的目录下面下载文件的操作
    估计与connect事件写的有关系,请看看我的connect事件有问题吗?
    ---------------------------------------------------------
    Private Sub winsock1_Connect()
        Dim strCommand As String
        On Error Resume Next    strCommand = "GET " + URL + " HTTP/1.0" + vbCrLf '其中URL为下载的URL
        strCommand = strCommand + "Accept: *.*, */*" + vbCrLf
        strCommand = strCommand + "User-Agent: Conquest" & vbCrLf
        strCommand = strCommand + "Referer: " & strSvrURL & vbCrLf
        strCommand = strCommand + vbCrLf
        Winsock1.SendData strCommand 
        
    End Sub
    ----------------------------------------
      

  7.   

    这是我修改后的源码,字节数大小没有那种问题了,但我传下来的文本文件的回车符都变为了■符号且都挤在了一行里,字节数也少得很有规律性:只要有回车的地方,就会少一个字符。比如有三行文本,就有两个回车,下载下来的数据就会少两个字节。DataArrival事件的源代码如下所示:----------------------------------------------------------
    Private Sub winsock1_DataArrival(ByVal bytesTotal As Long)
        Dim bytData() As Byte
        ReDim bytData(bytesTotal)        '定义一个数组存放每次发送来的数据。    Dim tmpData() As Byte            '保存第一次发送来的数据去掉头部信息后的数据
        
        Dim DATA As String               '保存二进制转为字符串时的字符串
        
        Winsock1.GetData bytData, vbByte + vbArray
        DATA = StrConv(bytData, vbUnicode)        '二进制转为字符串
        If InStr(DATA, "Content-Type:") Then
            Dim Pos%, LENGTH%, HEAD$
            Pos = InStr(DATA, vbCrLf & vbCrLf)
            LENGTH = Len(DATA)
            HEAD = Left(DATA, Pos - 1)
            DATA = Right(DATA, LENGTH - Pos - 3)
            Header = Header & HEAD
            bytesRemaining = GETDATAHEAD(Header, "Content-Length:")    '得到文件的大小
            tmpData = StrConv(DATA, vbFromUnicode)             '字符串转为二进制          '第一次写文件(去掉头后的数据写入指定文件中)
            Open FilePathName For Binary As #1
            Put #1, BytesAlreadySent, tmpData() 'writes data to the end of file
            BytesAlreadySent = Seek(1)
            Close #1
            Exit Sub
        End If    '将得到的数据写入文件
        Open FilePathName For Binary As #1   
        Put #1, BytesAlreadySent, bytData 
        BytesAlreadySent = Seek(1)
        Close #1End Sub
    --------------------------------------------------------------------
      

  8.   

    我看了connect事件代码应该没有什么问题
      

  9.   

    呵呵
    我感觉错误不像你说的那样,不是回车少什么字符了
    而是代码Put #1, BytesAlreadySent, bytData 应该改为
    Put #1, BytesAlreadySent+1, bytData 
    而且我觉得你不必要每次在有数据来时判断"Content-Type:",只要找到一次后,下次就不必再判断了,这样能够提高效率
      

  10.   

    不好意思,没有说明,我的BytesAlreadySent是设为的局部变量,在form_load事件里的时候就初始化为了1。所以,Put那句应该是没有问题的。但问题的确是这样:字节数大小没有那种问题了,但我传下来的文本文件的回车符都变为了■符号且都挤在了一行里,字节数也少得很有规律性:只要有回车的地方,就会少一个字符。比如有三行文本,就有两个回车,下载下来的数据就会少两个字节。
    真是百思不得一解!!!盼高人指点!!!
    好象是自动把文件里的回车替换为了换行加回车!(vbcrlf),这是为什么?!!!
      

  11.   

    我也写过网络程序,一般情况下不会出现回车符减少的问题我看了你的代码,我做了一些注释,你看看
    Private Sub winsock1_DataArrival(ByVal bytesTotal As Long)
        Dim bytData() As Byte
        ReDim bytData(bytesTotal)        '定义一个数组存放每次发送来的数据。    Dim tmpData() As Byte            '保存第一次发送来的数据去掉头部信息后的数据
        
        Dim DATA As String               '保存二进制转为字符串时的字符串
        
        Winsock1.GetData bytData, vbByte + vbArray
    ************
        DATA = StrConv(bytData, vbUnicode)        '二进制转为字符串
        如果说出现你说的vbcrlf的问题,就是在这条语句上出问题了,可能该函数是传址调用函数,会修改你的bytdata
    *************
        If InStr(DATA, "Content-Type:") Then
            Dim Pos%, LENGTH%, HEAD$
            Pos = InStr(DATA, vbCrLf & vbCrLf)
            LENGTH = Len(DATA)
            HEAD = Left(DATA, Pos - 1)
            DATA = Right(DATA, LENGTH - Pos - 3)
            Header = Header & HEAD
            bytesRemaining = GETDATAHEAD(Header, "Content-Length:")    '得到文件的大小
            tmpData = StrConv(DATA, vbFromUnicode)             '字符串转为二进制          '第一次写文件(去掉头后的数据写入指定文件中)
            Open FilePathName For Binary As #1
    *****************************
            Put #1, BytesAlreadySent, tmpData() 'writes data to the end of file
    如果你的BytesAlreadySent初值为1,则这条语句是对的
    但是还是建议你将BytesAlreadySent初值为0,将该语句改为
            Put #1, BytesAlreadySent+1, tmpData() 
    *****************************
    *****************************
            BytesAlreadySent = Seek(1)
    你看看MSDN,Seek语句是获得当前文件的操作位置
    *****************************
            Close #1
            Exit Sub
        End If    '将得到的数据写入文件
        Open FilePathName For Binary As #1   
    **************************    Put #1, BytesAlreadySent, bytData 
    所以,在下一次写入数据时,应该在上一次的位置上加1,在写入,否则会覆盖掉一个Byte,使文件变小
    所以我还是建议改为    Put #1, BytesAlreadySent+1, bytData ***************************
        BytesAlreadySent = Seek(1)
        Close #1End Sub