Перейти: неожиданный EOF при чтении из сокета
У меня есть следующая простая программа 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
Ответы
Ответ 1
Функция 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
.
Ответ 2
Вы также можете получить размер файла из заголовков HTTP и прочитать эту длину в своем сокете. Найдите заголовок ответа Content-Length.
Вы всегда должны знать размер того, что вы двигаете с помощью ввода-вывода, когда это файл и возможно, и ограничивать чтение до ожидаемого размера. Это позволит избежать многих проблем.
псевдокод:
$size = HTTP_RESPONSE['Content-Length'];
while(reading to $size)
{
do something with chunk;
}
Ответ 3
Документ не намного длиннее. Это всего лишь 412 байт дольше. Sine ReadFull не может прочитать все 1024 байта, которые он возвращает unexpected EOF
.