GoLang 文件传输停止且没有任何错误

azi*_*kim 3 go

我在go. 从服务器端我尝试一次读取 1024 字节的数据。从客户端我使用该io.Copy功能来传输文件。文件传输的成功率为 70%。但有 30% 的时间它会失败。它陷入了connection.Read功能困境。Read通过一些实验,我发现这种情况仅发生在先前操作读取的数据少于字节的情况下1024

因此,从我的代码来看,理想情况下它应该读取1024所​​有连续的数据字节,除了文件传输完成的Read最后一个。Read但在某些情况下,如果读取的字节数少于1024字节,则下一个Read操作将被卡住,而不会引发任何错误。这是我的代码:

  1. 服务器.go

    fileBuffer := make([]byte, BUFFER_SIZE)     //BUFFER_SIZE is a constant of 1024
    bytesRead := int64(0)
    count := 0
    for {
        if fileSize-bytesRead < int64(BUFFER_SIZE) {        //fileSize is the size of file in bytes, which I calculated earlier.
            fileBuffer = make([]byte, fileSize-bytesRead)
        }
    
        fmt.Println("Reading ", BUFFER_SIZE, " bytes of data")
    
        n, err := connection.Read(fileBuffer)
    
        count++
    
        fmt.Println("Completed reading", n, " bytes of data, count=", count)
    
        file.Write(fileBuffer[0:n])
    
        bytesRead += int64(n)
        fmt.Println("So far read", bytesRead, " bytes of data")
    
        if err != nil {
            fmt.Println(err)
        }
    
        if err == io.EOF {
            result.Message = "File transfer incomplete"
            break
        }
    
        if bytesRead >= fileSize {
            result.Message = "File transfer complete"
            break
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 客户端.go

    n, err := io.Copy(conn, file)
    fmt.Println(n, " bytes sent")
    
    Run Code Online (Sandbox Code Playgroud)

就我而言,发送的字节数是正确的,成功传输时接收的字节数也是正确的。同一个文件会出现此问题。

web*_*rc2 5

TL;DR:这应该是复制文件所需的全部内容。

if _, err := io.Copy(file, connection); err != nil {
    // handle error
}
Run Code Online (Sandbox Code Playgroud)

如果您需要分块复制,同时在副本之间执行一些逻辑(例如,打印读取的字节),您可以使用io.CopyN

totalRead := int64(0)
for {
    n, err := io.CopyN(outfile, infile, 1024)
    totalRead += n
    // print bytes read followed by a carriage return
    fmt.Printf("Bytes read: %d\r", totalRead)
    if err != nil {
        if err == io.EOF {
            fmt.Println() // print a newline
            break
        }
        // handle error
    }
}
Run Code Online (Sandbox Code Playgroud)