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
}
}