意外的EOF(文件结束符)在从套接字读取时发生

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

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(&amp;buf, fd)
if err != nil {
    die(&quot;dial read&quot;, 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[&#39;Content-Length&#39;];
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.

huangapple
  • 本文由 发表于 2011年10月29日 21:02:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/7939068.html
匿名

发表评论

匿名网友

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

确定