GoLang文件传输停止,无任何错误

GoLang文件传输停止,无任何错误,go,Go,我在go中运行了一个简单的文件传输代码。从服务器端,我尝试一次读取1024字节的数据。在客户端,我使用io.Copy函数传输文件。文件传输成功完成的时间占70%。但在30%的时间里,它失败了。它卡在连接上。读取功能。通过一些实验,我发现这种情况只发生在以前的Read操作读取的数据少于1024字节的情况下 因此,从我的代码中,理想情况下,它应该在所有连续的read上读取1024字节的数据,但最后一次read的文件传输完成时除外。但在某些情况下,如果读取的字节数小于1024字节,则下一个Read操作

我在
go
中运行了一个简单的文件传输代码。从服务器端,我尝试一次读取1024字节的数据。在客户端,我使用
io.Copy
函数传输文件。文件传输成功完成的时间占70%。但在30%的时间里,它失败了。它卡在
连接上。读取
功能。通过一些实验,我发现这种情况只发生在以前的
Read
操作读取的数据少于
1024
字节的情况下

因此,从我的代码中,理想情况下,它应该在所有连续的
read
上读取
1024
字节的数据,但最后一次
read
的文件传输完成时除外。但在某些情况下,如果读取的字节数小于
1024
字节,则下一个
Read
操作将被卡住而不会抛出任何错误。这是我的密码:

  • Server.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
        }
    }
    

  • 对于我的情况,成功传输时发送的字节数是正确的,接收的字节数也是正确的。问题发生在同一个文件中。

    TL;DR:这就是你复制文件所需要的全部

    if _, err := io.Copy(file, connection); err != nil {
        // handle error
    }
    
    如果在副本之间执行某些逻辑(例如,打印读取的字节)时需要分块复制,可以使用


    您没有在非EOF错误上中断,这可能会卡住,并且您没有检查写入计数或错误。为什么不直接使用io.Copy或io.CopyBuffer?是的,我不会因为非EOF错误而中断。但如果有任何错误,我正在打印。所以在出错的情况下,我希望在控制台上看到一些东西。这只是一个测试应用程序,我不需要它是完美的。我只需要理解为什么文件传输有时会被卡住。另外,我正在使用io.Copy并打印从客户端发送的字节数,这总是正确的。在写入文件之前,您一定要检查错误。如果发生错误(不一定定义
    n
    ),请不要写入文件。我非常感谢。这是一个更好更干净的代码,我将用它替换我的代码。但我也想知道我的代码出了什么问题。这里似乎没有什么不正确的地方。是的,这可能是一个原因,但事实并非如此。因为每次阅读后我都会打印一张。如果是无限循环,我会在控制台上看到无限打印。为了再次检查,我删除了新的缓冲区分配,并进行了一些额外的打印,这证实了我的代码中没有这种情况。事实上,我对您的代码也有同样的问题。它会在某个时刻卡住。不确定出了什么问题。听起来你的连接有问题(可能是发送方、网络或你的connection.Read()方法有问题)。
    if _, err := io.Copy(file, connection); err != nil {
        // handle error
    }
    
    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
        }
    }