I've written an itty bitty tcp server, for educational purposes.
The program outputs a file if you input the correct hash (or whatever you set the environment variable to).
I've performed tests on the application through netcat ( nc localhost 9000
) and everything is fine, the application works as intended, both in my docker container and running "standalone".
Here's the 80 lines of code.
package main
import (
"fmt"
"io"
"io/ioutil"
"net"
"bytes"
"os"
"log"
)
var OUTPUT_FILE = os.Getenv("OUTPUT_FILE")
var SECRET_HASH = os.Getenv("SECRET_HASH")
func handleError(e error) {
if e != nil {
log.Fatal(e)
panic(e)
}
}
func printFromFile(connection net.Conn) {
/* Read file */
data, err := ioutil.ReadFile(OUTPUT_FILE)
handleError(err)
/* Close connection */
io.WriteString(connection, string(data))
connection.Close()
}
func invalidHashMessage(connection net.Conn) {
io.WriteString(connection, fmt.Sprint("Invalid hash\n"))
}
func handleMessage(connection net.Conn) {
buffer := make([]byte, 1024)
reqLen, err := connection.Read(buffer)
if reqLen == 0 {
connection.Close()
return
}
handleError(err)
n := bytes.Index(buffer, []byte{0})
message := string(buffer[:n-1])
if message != SECRET_HASH {
invalidHashMessage(connection)
handleMessage(connection)
} else {
printFromFile(connection)
}
}
func main() {
if OUTPUT_FILE == "" || SECRET_HASH == "" {
fmt.Print("You need to supply output file and hash to serve application\n")
os.Exit(1)
}
/* Start listener */
ln, err := net.Listen("tcp", ":9000")
handleError(err)
defer ln.Close()
for {
conn, err := ln.Accept()
handleError(err)
io.WriteString(conn, "Please type unique identifier:")
go handleMessage(conn)
}
}
So.. my questions are.
- How would you handle concurrent connections? Making it real pretty. I have a certain feeling this could be improved upon, or is this way totally ok?
- Am i formatting the message correctly (the file content) so that available clients/terminals that access this little application all works the same?
When i run this application through strace i get the following message which is saying that the port is already taken (?), but the application runs just fine. Trying to understand why strace outputs this.
accept4(3, 0xc420051c00, [112], SOCK_CLOEXEC|SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable)