I am trying to make TCP server for transferring files. I am suing io.CopyN for reading and writing. From server side, I am sending files to client so from server side, it sends perfectly all bytes but Client side after reading a couple of 1000000 bytes it stuck. sometimes it works fine and sometimes it gets stuck. I am using 300 MB pdf to test. Any help, code, and output is like below.
//server
package main
import (
"fmt"
"io"
"log"
"net"
"os"
"strconv"
"strings"
)
func main() {
fmt.Println("In server \n")
ls, err := net.Listen("tcp", ":1234")
defer ls.Close()
if err != nil {
panic(err)
}
i := 1
for {
conn, _ := ls.Accept()
var check string
var check1 string
defer conn.Close()
for {
fmt.Println("Do you want to send more : ")
fmt.Scanf("%s", &check1)
if check == "n" {
break
}
file, err := os.Open(strings.TrimSpace("./" + "Mag" + ".pdf"))
if err != nil {
fmt.Println("inside error 111 : ", i)
log.Fatal(err)
}
defer file.Close()
fileInfo, err := file.Stat()
if err != nil {
fmt.Println("in stat")
}
size := fileInfo.Size()
numberOfTime := size / 1000000
leftByte := size - numberOfTime*1000000
numberOfTimeString := strconv.Itoa(int(numberOfTime))
leftByteString := strconv.Itoa(int(leftByte))
fmt.Println("1000000 times : ", numberOfTimeString)
fmt.Println("Left Bytes : ", leftByteString)
sizeSent, err := fmt.Fprintf(conn, numberOfTimeString+"\n")
if err != nil {
panic(err)
}
sizeSent, err = fmt.Fprintf(conn, leftByteString+"\n")
if err != nil {
panic(err)
}
fmt.Println(sizeSent)
fileWriter := io.Writer(conn)
n, err := io.CopyN(fileWriter, file, size)
if err == io.EOF {
fmt.Println(err, n)
}
fmt.Println(n, "bytes sent")
if err != nil {
log.Println(err)
}
file.Close()
}
}
fmt.Println("We are done with server")
}
//client
//client
package main
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"os"
"os/signal"
"strconv"
"strings"
"syscall"
)
func main() {
c := make(chan os.Signal, 15)
signal.Notify(c, syscall.SIGINT)
go func() {
for {
s := <-c
switch s {
case syscall.SIGINT:
removeDir()
os.Exit(1)
}
}
}()
defer removeDir()
conn, err := net.Dial("tcp", ":1234")
if err != nil {
panic(err)
}
defer conn.Close()
connReadWrite := bufio.NewReader(io.Reader(conn))
var i int
var filename string
for {
i++
if i > 15 {
break
}
nu := strconv.Itoa(i)
os.MkdirAll("./"+nu+"/", os.ModePerm)
filename = "./" + nu + "/image" + nu + ".pdf"
file, err := os.Create(filename)
defer file.Close()
if err != nil {
panic(err)
}
l1, err := connReadWrite.ReadString('\n')
if err != nil {
println(err)
}
println("\n1000000 times :", l1)
l1 = strings.TrimSuffix(l1, "\n")
nb1, err := strconv.Atoi(l1)
if err != nil {
panic(err)
}
l2, err := connReadWrite.ReadString('\n')
if err != nil {
println(err)
}
println("Left Bytes :", l2)
l2 = strings.TrimSuffix(l2, "\n")
nb2, err := strconv.Atoi(l2)
if err != nil {
panic(err)
}
fmt.Println("After convert in Num :", nb1, nb2)
newFileWriter := io.Writer(file)
newFileReader := io.Reader(conn)
for i := 0; i < nb1; i++ {
n, err := io.CopyN(newFileWriter, newFileReader, 1000000)
if i >= 31 {
errFun(err, n)
}
}
n, err := io.CopyN(newFileWriter, newFileReader, int64(nb2))
errFun(err, n)
file.Close()
}
fmt.Println("We are done with client ")
}
func errFun(err error, n int64) {
if err == io.EOF {
fmt.Println("End of file : ", n)
return
} else if n == 0 {
fmt.Println("n is : ", n)
return
} else if err != nil {
fmt.Println(err)
return
}
fmt.Println(err, " : ", n)
}
func removeDir() {
var dir []string
files, err := ioutil.ReadDir("./")
if err != nil {
log.Fatal(err)
}
for _, f := range files {
dir = append(dir, f.Name())
}
for i, dname := range dir {
if i < 1 {
continue
}
file, err := os.Open("./" + dname)
fileInfo, err := file.Stat()
if !fileInfo.IsDir() {
file.Close()
continue
}
err = os.RemoveAll(dname)
if err != nil {
log.Fatal(err)
}
file.Close()
}
input/output
from server side when press Y it sends data after the client side it gets a number of bytes it needs to read and then I am sending the file and then it read. In the picture, I was able to send two-time third time it got stuck sometimes it stuck first time too. when stuck if press cnt+C it gets End of file err. i just don’t understand this