英文:
Go: unexpected EOF while reading from a socket
问题
我有以下简单的golang程序来下载Google的隐私政策。不幸的是,它总是在读取了6861个字节后崩溃,并显示错误unexpected EOF
,即使文档要长得多。为什么?
package main
import "net"
import "fmt"
import "io"
import "os"
func die(msg string, s os.Error) {
fmt.Printf("%s crashed: %v\n", msg, s)
os.Exit(1)
}
func main() {
fd, err := net.Dial("tcp", "google.com:80")
if err != nil { die("dial", err) }
req := []byte("GET /intl/en/privacy/ HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
_, err = fd.Write(req)
if err != nil { die("dial write", err) }
buf := make([]byte, 1024)
nr := 1
for nr > 0 {
nr, err = io.ReadFull(fd, buf)
if err != nil { die("dial read", err) }
fmt.Printf("read %d\n", nr)
}
}
输出:
read 1024
read 1024
read 1024
read 1024
read 1024
read 1024
dial read crashed: unexpected EOF
英文:
I have the following simple golang program to download Google's privacy policy. Unfortunately it always crashes with the error unexpected EOF
after reading 6861 bytes, even though the document is much longer. Why?
package main
import "net"
import "fmt"
import "io"
import "os"
func die(msg string, s os.Error) {
fmt.Printf("%s crashed: %v\n", msg, s)
os.Exit(1)
}
func main() {
fd, err := net.Dial("tcp", "google.com:80")
if err != nil { die("dial", err) }
req := []byte("GET /intl/en/privacy/ HTTP/1.0\r\nHost: www.google.com\r\n\r\n")
_, err = fd.Write(req)
if err != nil { die("dial write", err) }
buf := make([]byte, 1024)
nr := 1
for nr > 0 {
nr, err = io.ReadFull(fd, buf)
if err != nil { die("dial read", err) }
fmt.Printf("read %d\n", nr)
}
}
outputs:
read 1024
read 1024
read 1024
read 1024
read 1024
read 1024
dial read crashed: unexpected EOF
答案1
得分: 12
Function io.ReadFull(fd, buf)
应该只在你知道fd
至少可以提供len(buf)
字节的情况下使用。
相反,尝试以下方法:
var buf bytes.Buffer
nr, err := io.Copy(&buf, fd)
if err != nil {
die("dial read", err)
}
如果要复制到文件,请使用os.File
而不是bytes.Buffer
。
英文:
Function <code>io.ReadFull(fd, buf)</code> should be used only when you know that <code>fd</code> can feed at least <code>len(buf)</code> bytes.
Instead, try the following:
var buf bytes.Buffer
nr, err := io.Copy(&buf, fd)
if err != nil {
die("dial read", err)
}
If copying to a file, use an <code>os.File</code> instead of <code>bytes.Buffer</code>.
答案2
得分: 4
你还可以从HTTP头部获取文件的大小,并根据该大小在套接字上读取。查找Content-Length响应头。
当使用IO移动文件时,你应该始终知道所移动内容的大小,并将读取限制在预期大小范围内。这将避免许多问题。
伪代码:
$size = HTTP_RESPONSE['Content-Length'];
while(读取至$size)
{
对块进行操作;
}
英文:
You can also get the size of the file from the HTTP headers, and read to that length on your socket. Look for Content-Length response header.
You should always know the size of what you are moving with IO, when it's a file and possible, and limit your read to the expected size. This will avoid a lot of issues.
pseudocode:
$size = HTTP_RESPONSE['Content-Length'];
while(reading to $size)
{
do something with chunk;
}
答案3
得分: 3
文档并不长。只多了412个字节。由于ReadFull无法读取全部1024个字节,它返回了unexpected EOF
。
英文:
The document is not much longer. It's only 412 bytes longer. Sine ReadFull cannot read all 1024 bytes it returns unexpected EOF
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论