I'm writing an FTP server in Go and I've run into a problem when listing the files/directories. What seems to be happening is that the server is sending the files each separately and correctly but when reading them from the connection, they get read multiple at a time.
I've tried changing the buffer size as well as sending a confirmation before sending each file name yet when reading from the connection it ends up reading more bytes than expected.
This is the relative part from the server:
for _, fn := range files {
conn.Write([]byte(fn.Name()))
}
In the code above, files
is []os.FileInfo
from ioutil.ReadDir("./")
to get the files in the current directory. When tested this sends the correct file name as well as the correct bytes for each name.
On the client I have this:
var buf [256]byte
for i := 0; i < int(amnt); i++ {
n, err = conn.Read(buf[:])
if err != nil {
fmt.Printf("Error getting files: %s
", err)
}
fmt.Printf("%s
", string(buf[:n]))
}
int(amnt)
is just an int
for how many files are in the directory and is correct.
The server sends everything correctly so I am sure that the problem lies in reading into buf
but I can't figure out why it would be reading in more than one file name at a time.
One strategy to address this could be to develop a loose structured protocol which will involve having the client delineate files and the server parse files. This might be done by sending a new line after each file that the client writes. This way the server can scan lines from the TCP connection using go's Scanner
:
for _, fn := range files {
conn.Write([]byte(fn.Name()))
conn.Write([]byte(`
`))
}
scanner := bufio.NewScanner(conn)
for {
if ok := scanner.Scan(); !ok {
break
}
fmt.Println(scanner.Text())
}
fmt.Println("Scanning ended")
Go makes this possible because the TCP connection implements the io.Reader interface.