Go: неожиданный EOF при чтении из сокета - PullRequest
14 голосов
/ 29 октября 2011

У меня есть следующая простая программа golang для загрузки политики конфиденциальности Google.К сожалению, он всегда вылетает с ошибкой unexpected EOF после считывания 6861 байта, хотя документ намного длиннее.Почему?

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

Ответы [ 3 ]

11 голосов
/ 30 октября 2011

Функция 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.

4 голосов
/ 14 августа 2013

Вы также можете получить размер файла из заголовков HTTP и прочитать до этой длины в своем сокете.Ищите заголовок ответа Content-Length.

Вы всегда должны знать размер того, что вы перемещаете с помощью ввода-вывода, когда это файл и возможно, и ограничивать чтение до ожидаемого размера.Это позволит избежать многих проблем.псевдокод:

$size = HTTP_RESPONSE['Content-Length'];
while(reading to $size)
{
    do something with chunk;
}
3 голосов
/ 29 октября 2011

Документ не намного дольше. Это всего на 412 байт длиннее. Sine ReadFull не может прочитать все 1024 байта, которые он возвращает unexpected EOF.

...