Skip to content

Instantly share code, notes, and snippets.

@kehiy
Created June 21, 2023 10:33
Show Gist options
  • Save kehiy/4bff455048a8bedf4f9374b8899b2f43 to your computer and use it in GitHub Desktop.
Save kehiy/4bff455048a8bedf4f9374b8899b2f43 to your computer and use it in GitHub Desktop.
Stream large files over a TCP connection.
package main
import (
"bytes"
"crypto/rand"
"encoding/binary"
"fmt"
"io"
"log"
"net"
"time"
)
type FileServer struct { }
func (fs *FileServer) start() {
ln, err := net.Listen("tcp", "0.0.0.0:3000")
if err != nil {
panic(err)
}
for {
conn, err := ln.Accept()
if err != nil {
log.Fatal(err)
continue
}
fmt.Printf("new connection: %s\n", conn.RemoteAddr().String())
// read data from accepted connections
go fs.readLoop(conn)
}
}
func (fs *FileServer) readLoop(conn net.Conn) {
// make a new buffer
buf := new(bytes.Buffer)
for {
var size int64
// get the size from connection
binary.Read(conn, binary.LittleEndian, &size)
// copy from connection until the end of file
n, err := io.CopyN(buf, conn, size)
if err != nil {
log.Fatal(err)
continue
}
fmt.Println(buf.Bytes())
fmt.Printf("received %d bytes over the network\n", n)
}
}
func main() {
go func () {
time.Sleep(4 * time.Second)
// set your file szie
sendFile(2000000)
}()
s := &FileServer{}
s.start()
}
func sendFile(size int) error {
file := make([]byte, size)
// make a random file from the size provided
_, err := io.ReadFull(rand.Reader, file)
if err != nil {
return err
}
// dial with the tcp server (you can do this is an other file)
conn, err := net.Dial("tcp", ":3000")
if err != nil {
return err
}
// send the size of file
binary.Write(conn, binary.LittleEndian, int64(size))
// copy file over the network until the end of file
n, err := io.CopyN(conn, bytes.NewReader(file), int64(size))
if err != nil {
return err
}
fmt.Printf("written %d byte over the network\n", n)
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment