Я пишу простой пример кода, он работает, но размер полученного файла не сжимается
Мой клиент (для подключения к серверу и отправки файла):
// connect to server
conn, err := net.Dial("tcp", serverAddr)
CheckError(err)
defer conn.Close()
in, err := os.Open(srcFile)
if err != nil {
log.Fatal(err)
}
pr, pw := io.Pipe()
gw, err := gzip.NewWriterLevel(pw, 7)
CheckError(err)
go func() {
n, err := io.Copy(gw, in)
gw.Close()
pw.Close()
log.Printf("copied %v %v", n, err)
}()
//maybe error some next?
_, err = io.Copy(conn, pr)
Помогите, пожалуйста, как правильно использовать pipe с копией
Потому что мне нужно сжимать файл "на лету" и передавать сжатые данные
Трубу не требуется сжимать на лету.
Ваш код работает, кстати
Я не умею писать без трубы. Мой файл для передачи такого большого размера (~ 4 ГБ) и выделения большого буфера - плохая идея. Может быть, вы можете написать небольшой пример? Спасибо!
Как я уже сказал в комментарии, ваш код работает. Я создал небольшой пример, чтобы проверить или посмотреть, смогу ли я решить вашу проблему. Так что, я думаю, вы можете закрыть этот вопрос.
package main
import (
"compress/gzip"
"io"
"log"
"net"
"os"
)
func main() {
// Create a listener on a random port.
listener, err := net.Listen("tcp", "127.0.0.1:")
if err != nil {
log.Fatal(err)
}
log.Println("Server listening on: " + listener.Addr().String())
done := make(chan struct{})
go func() {
defer func() { done <- struct{}{} }()
for {
conn, err := listener.Accept()
if err != nil {
log.Println(err)
return
}
go func(c net.Conn) {
defer func() {
c.Close()
done <- struct{}{}
}()
buf := make([]byte, 1024)
for {
n, err := c.Read(buf)
if err != nil {
if err != io.EOF {
log.Println(err)
}
return
}
log.Printf("received: %q", buf[:n])
log.Printf("bytes: %d", n)
}
}(conn)
}
}()
conn, err := net.Dial("tcp", listener.Addr().String())
if err != nil {
log.Fatal(err)
}
log.Println("Connected to server.")
file, err := os.Open("./file.txt")
if err != nil {
log.Fatal(err)
}
pr, pw := io.Pipe()
w, err := gzip.NewWriterLevel(pw, 7)
if err != nil {
log.Fatal(err)
}
go func() {
n, err := io.Copy(w, file)
if err != nil {
log.Fatal(err)
}
w.Close()
pw.Close()
log.Printf("copied to piped writer via the compressed writer: %d", n)
}()
n, err := io.Copy(conn, pr)
if err != nil {
log.Fatal(err)
}
log.Printf("copied to connection: %d", n)
conn.Close()
<-done
listener.Close()
<-done
}
Вывод этой программы с простым текстовым файлом с множеством повторяющихся символов, чтобы было что сжимать: Файл имеет размер 153 байта, а я отправляю/получаю 46 байтов.
2022/04/04 11:23:58 Server listening on: 127.0.0.1:58250
2022/04/04 11:23:58 Connected to server.
2022/04/04 11:23:58 received: "\x1f\x8b\b\x00\x00\x00\x00\x00\x00\xff"
2022/04/04 11:23:58 bytes: 10
2022/04/04 11:23:58 copied to piped writer via the compressed writer: 153
2022/04/04 11:23:58 copied to connection: 46
2022/04/04 11:23:58 received: "*I-.I,NI,N\xc1\x01\x8aS\x8a\x13i\bx\xb9pX \r\b\x00\x00\xff\xff\xc7\xfe\xa6c\x99\x00\x00\x00"
2022/04/04 11:23:58 bytes: 36
2022/04/04 11:23:58 accept tcp 127.0.0.1:58250: use of closed network connection
Да, спасибо за тест, но я знаю, что мой пример передал файл. Моя проблема в том, что полученный файл не сжат. Насколько я понимаю, я копирую данные из pr в соединение, и это не сжатые данные. Я добавляю полный пример в pastebin. Сервер: pastebin.com/PUKuQi7q Клиент: pastebin.com/K8H91Sqq
если вы попробуете мой пример, вы увидите, что полученные байты намного меньше, чем фактический файл, также вы можете увидеть данные, сжатые gzip.
Да! Благодарю вас! Моя проблема не вызывает другого объекта в горутине
Каково назначение трубы? Почему бы не написать напрямую в подключение?