我在go
中运行了一个简单的文件传输代码。从服务器端,我尝试一次读取1024字节的数据。从客户端我使用io.Copy
函数传输文件。文件传输在70%的时间内成功完成。但是在30%的时间里它失败了。它卡在connection.Read
函数上。通过一些实验,我发现它只发生在以前的Read
操作读取的数据少于1024
字节的情况下。
因此,从我的代码中,理想情况下,除了文件传输完成的最后1024
之外,它应该在所有后续Read
上读取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
}
}
Client.go
n, err := io.Copy(conn, file)
fmt.Println(n, " bytes sent")
对于我的情况,发送的字节数是正确的,成功传输时接收的字节数也是正确的。问题发生在同一个文件中。
答案 0 :(得分:2)
TL; DR:这应该是复制文件所需的全部内容。
if _, err := io.Copy(file, connection); err != nil {
// handle error
}
如果您需要在副本之间执行某些逻辑时复制块(例如,打印读取的字节),则可以使用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
}
}