GoLang文件传输在没有任何错误的情况下停止

huangapple go评论82阅读模式
英文:

GoLang File Transfer Stops Without Any Error

问题

我正在运行一个简单的文件传输代码,使用go语言。从服务器端,我尝试每次读取1024字节的数据。从客户端,我使用io.Copy函数来传输文件。文件传输成功完成的概率为70%。但是在30%的情况下会失败。它在connection.Read函数上卡住。通过一些实验,我发现只有在之前的Read操作读取的数据少于1024字节的情况下才会发生这种情况。

所以根据我的代码,理想情况下,除了最后一个Read操作,在所有连续的Read操作中都应该读取1024字节的数据。但是在某些情况下,如果读取的字节数少于1024,下一个Read操作会卡住而不抛出任何错误。以下是我的代码:

  1. Server.go
fileBuffer := make([]byte, BUFFER_SIZE) // BUFFER_SIZE是一个常量,值为1024
bytesRead := int64(0)
count := 0
for {
    if fileSize-bytesRead < int64(BUFFER_SIZE) { // fileSize是文件的字节数,我之前计算得到的
        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 = "文件传输不完整"
        break
    }

    if bytesRead >= fileSize {
        result.Message = "文件传输完成"
        break
    }
}
  1. Client.go
n, err := io.Copy(conn, file)
fmt.Println(n, "bytes sent")

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

英文:

I've running a simple file transfer code in go. From the server side I try to read 1024 bytes of data at a time. From client side I'm using the io.Copy function to transfer the file. The file transfer completes successfully 70% of the time. But in 30% of time it fails. It gets stuck on connection.Read function. Through some experiments I saw that it happens only on the occasion where previous Read operation reads less than 1024 bytes of data.

So from my code, ideally it should read 1024 bytes of data on all successive Read except the very last Read where the file transfer is complete. But on some occasion if it reads less than 1024 bytes, the next Read operation gets stuck without throwing any error. Here is my code:

  1. Server.go

    fileBuffer := make([]byte, BUFFER_SIZE)		//BUFFER_SIZE is a constant of 1024
    bytesRead := int64(0)
    count := 0
    for {
    	if fileSize-bytesRead &lt; int64(BUFFER_SIZE) {		//fileSize is the size of file in bytes, which I calculated earlier.
    		fileBuffer = make([]byte, fileSize-bytesRead)
    	}
    
    	fmt.Println(&quot;Reading &quot;, BUFFER_SIZE, &quot; bytes of data&quot;)
    
    	n, err := connection.Read(fileBuffer)
    
    	count++
    
    	fmt.Println(&quot;Completed reading&quot;, n, &quot; bytes of data, count=&quot;, count)
    
    	file.Write(fileBuffer[0:n])
    
    	bytesRead += int64(n)
    	fmt.Println(&quot;So far read&quot;, bytesRead, &quot; bytes of data&quot;)
    
    	if err != nil {
    		fmt.Println(err)
    	}
    
    	if err == io.EOF {
    		result.Message = &quot;File transfer incomplete&quot;
    		break
    	}
    
    	if bytesRead &gt;= fileSize {
    		result.Message = &quot;File transfer complete&quot;
    		break
    	}
    }
    
  2. Client.go

    n, err := io.Copy(conn, file)
    fmt.Println(n, &quot; bytes sent&quot;)
    

For my case, number of sent bytes is correct, number of received bytes is also correct on successful transfer. The problem happens for the same file.

答案1

得分: 5

TL;DR: 这是你需要复制文件的全部代码。

if _, err := io.Copy(file, connection); err != nil {
    // 处理错误
}

如果你需要在复制过程中分块复制,并在复制之间执行一些逻辑(例如,打印读取的字节数),你可以使用 io.CopyN

totalRead := int64(0)
for {
    n, err := io.CopyN(outfile, infile, 1024)
    totalRead += n
    // 打印读取的字节数,后面跟一个回车符
    fmt.Printf("读取的字节数:%d\r", totalRead)
    if err != nil {
        if err == io.EOF {
            fmt.Println() // 打印一个换行符
            break
        }
        // 处理错误
    }
}
英文:

TL;DR: This should be all you need to copy a file.

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

If you need to copy in chunks while doing some logic in between copies (for example, printing the bytes read), you can use 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(&quot;Bytes read: %d\r&quot;, totalRead)
	if err != nil {
		if err == io.EOF {
			fmt.Println() // print a newline
			break
		}
		// handle error
	}
}

huangapple
  • 本文由 发表于 2016年11月5日 01:59:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/40429072.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定