【问题标题】:VB.Net File Transfer: Incomplete Received FilesVB.Net 文件传输:接收到的文件不完整
【发布时间】:2016-04-21 15:16:59
【问题描述】:

我在VB.Net中创建了一个文件共享程序,但是当我尝试发送文件时,接收部分没有正确接收文件。只有我发送的文件的一部分。比如说,我发送了一个 100 MB 的文件,只会收到 10 MB。有时 22 KB、39MB 等。接收到的文件的大小并不总是相同的。你认为是什么导致了这个问题?我应该怎么做才能正确接收整个文件?

发送部分

Sub Main()
    Dim ip As New IPEndPoint(IPAddress.Any, 8888)' Port Server
    Dim sock As New Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream,   ProtocolType.IP)' Protocol type
    sock.Bind(ip)
    sock.Listen(100)
    While True' Check Client Connection
        Try
           msg("Accept Client Connect")
           Dim csock As Sockets.Socket = sock.Accept
           Dim csend(1024 * 10000) As Byte
           Dim path As String = "C:\Users\IT\Desktop\test\" ' Location to save file
           Dim bLen As Integer = csock.Receive(csend) ' Byte Read Len
           Dim fileLen As Integer = BitConverter.ToInt32(csend, 0) ' File Len
           Dim fName As String = Encoding.ASCII.GetString(csend, 4, fileLen) ' File Name
           msg("Start Receive....." & fName)
           Dim bWrite As New BinaryWriter(File.Open(path + fName, FileMode.Append))
           bWrite.Write(csend, 4 + fileLen, bLen - 4 - fileLen)
           msg("File receiced and Save " & path)
           bWrite.Close()
           csock.Close()
       Catch ex As Exception
           msg(ex.Message)
       End Try
    End While
    Console.ReadLine()
End Sub

Sub msg(ByVal mesg As String)
mesg.Trim()
Console.WriteLine(" >> " + mesg)
End Sub

接收部分

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)     Handles Button2.Click
    Dim ipServer As IPAddress() = Dns.GetHostAddresses("127.0.0.1") ' IP Server
    Dim ip As IPEndPoint = New IPEndPoint(ipServer(0), 8888)
    Dim csock As Socket = New Socket(AddressFamily.InterNetwork, SocketType.Stream,     ProtocolType.IP)
    Dim fName As String = TextBox1.Text
    Dim path As String = TextBox2.Text
    Dim fNameByte() As Byte = Encoding.ASCII.GetBytes(fName)
    Dim fData() As Byte = File.ReadAllBytes(path & "\" & fName)
    Dim cData(4 + fName.Length + fData.Length) As Byte
    Dim fDataLen() As Byte = BitConverter.GetBytes(fNameByte.Length)
    Try
       fDataLen.CopyTo(cData, 0)
       fNameByte.CopyTo(cData, 4)
       fData.CopyTo(cData, 4 + fNameByte.Length)
       csock.Connect(ip)
       csock.Send(cData)
       MsgBox("Success Send File ")
       csock.Close()
    Catch ex As Exception
       MsgBox(ex.Message)
    End Try
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)  Handles Button1.Click
    If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
    TextBox1.Text = System.IO.Path.GetFileName(OpenFileDialog1.FileName)
    TextBox2.Text = System.IO.Path.GetDirectoryName(OpenFileDialog1.FileName)
    End If
End Sub

【问题讨论】:

  • 您希望只用一次 Receive() 调用即可获得整个文件。那是行不通的,你必须继续调用 Receive() 直到你收到所有的字节。
  • 好的。感谢那。所以,这意味着我需要按块获取字节。还有一个问题,我可以通过网络发送的最大字节块大小是多少?
  • 没有分块,TCP 是一个。每次 Receive() 调用都会获得不可预测的字节数。发送它更容易,Send() 调用将简单地阻塞,直到可以发送字节。您通常使用一个循环,在其中一次从文件中读取 4096 个字节并发送()它们。这是使用非常少的内存并防止在文件很大时程序崩溃的好方法。
  • 好的。我现在明白了这个概念。但是我怎样才能得到接收部分的总文件大小呢?我的意思是,如果我得到不可预测的字节数,如果我不知道该文件的总大小是多少,我将如何重建该文件? bytesRead < totalSize 之类的东西,我可以将其用作条件循环的条件。
  • 没关系。我得到它。当没有数据读取时,意味着读取的字节等于0,那么接收部分的循环必须停止。感谢您的时间和建议。真的帮了大忙! :)

标签: .net vb.net sockets file-transfer


【解决方案1】:

错误 1, a 使用 Append 模式创建了二进制文件,该模式应该是 Create line 07

错误 2, 应该使用嵌套循环来接收数据包。在这里我添加 do ~ 循环。 a if 条件检查天气是否有另一个数据包可用,通过检查它的大小,如果 size=0 则在 08 ~ 13 行退出循环

错误3,当收到第一个数据包时,它被写入文件中减去元数据。比如 bWrite.Write(csend,4+fileLen,bLen-4-fileLen)。在 06/10 行 这对于第一个数据包来说很好,但对于剩余的数据包则不然.因为元数据在开始时只发送一次,所以它不应该从每个数据包中删除。在这种情况下,剩余值应为 0,并且数据包的长度为 bLen。正如您在 第 12 行所看到的,我正在重置这些值。

         01,   Dim csock As Sockets.Socket = sock.Accept
         02,   Dim csend(1024 * 10000) As Byte
         03,   Dim bLen As Integer = csock.Receive(csend) ' Byte Read Len
         04,   Dim fileLen As Integer = BitConverter.ToInt32(csend, 0) ' File Len
         05,   Dim fName As String = Encoding.ASCII.GetString(csend, 4, fileLen) ' File Name
         06,   Dim strt As Integer = 4 + fileLen, ln As Integer = bLen - 4 - fileLen

         07,   Dim bWrite As New BinaryWriter(File.Open(path + fName, FileMode.Create))
         08,   Do
         09,       If bLen = 0 Then Exit Do
         10,       bWrite.Write(csend, strt, ln)
         11,       bLen = csock.Receive(csend) ' Byte Read Len
         12,       strt = 0 : ln = bLen
         13,   Loop

对不起,我尽力解释它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 2016-01-18
    • 2015-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多