The godocs say:
"EOF is the error returned by Read when no more input is available. Functions should return EOF only to signal a graceful end of input. If the EOF occurs unexpectedly in a structured data stream, the appropriate error is either ErrUnexpectedEOF or some other error giving more detail."
and in my program I would love
love to get ErrUnexpectedEOF, but I don't. I always get just EOF even when the client terminates in the middle of sending a file.
so, i'm stuck. Successful files that transfer 100% of the way thru send EOF at end. And files that quit 50% thru with error also send EOF as the error. I do not know the total size of the file before the transfer.
Is there any more information I could get from the net.TCPConn to know was this a full file or not?
TCP is a streaming protocol; a stream of bytes. That's why file transfer protocols invented/implemented upon TCP, like FTP (File Transfer Protocol).
But (not recommended/thought experiment) if you can send your files in chunks that does not contain a certain character/byte (like base64 + as that certain character), then you can use that certain character as delimiter.
Now if we handle our connections using a function similar to this:
func (srv *Server) handler(conn net.Conn) {
//...
defer srv.closeConnection(conn, nil)
reader := bufio.NewReader(conn)
writer := bufio.NewWriter(conn)
//...
conn.SetDeadline(time.Now().Add(conf.ClientTimeout))
for {
select {
case <-conf.QuitSignal:
return
default:
line, err := reader.ReadBytes('
')
if err != nil {
return
}
//...
}
conn.SetDeadline(time.Now().Add(conf.ClientTimeout))
}
}
func (srv *Server) closeConnection(conn net.Conn, err error) {
conn.Close()
//...
}
From the documentation of Reader.ReadBytes
we read ReadBytes returns err != nil if and only if the returned data does not end in delimiter. This way we can recognize a broken chunk.