I am trying to learn the net
package. I am listening for local connections on a port, and sending data to that port using echo -n "Server test. " | nc localhost 5000
.
I always get an EOF
error when reading the data, however. I checked the docs and this is only supposed to happen when there is no more input available, however I don't understand why this is happening here.
This is my code:
package main
import (
"bufio"
"fmt"
"net"
"os"
)
// Connection details
type connection struct {
host string
port string
network string
}
// Initialise a Listener on a given port
// Pass handling into seperate goroutine
func main() {
localConn := connection{
host: "", // Localhost
port: "5000",
network: "tcp",
}
listener, err := net.Listen(localConn.network, localConn.host+":"+localConn.port)
checkError("Error listening: ", err)
conn, err := listener.Accept()
for {
checkError("Error accepting: ", err)
go handleRequest(conn)
}
}
// Delegate handling of requests
func handleRequest(conn net.Conn) {
// Read message up until newline delimiter
message, err := bufio.NewReader(conn).ReadString('
')
checkError("Error reading: ", err)
fmt.Println("Message recieved: ", string(message))
conn.Write([]byte("Recieved message: " + string(message) + "
"))
conn.Close()
}
// Check if an error exists
// If so, print and exit program. (Not super robust!)
func checkError(message string, err error) {
if err != nil {
fmt.Println(message, err.Error())
os.Exit(1)
}
}
One problem is on these lines:
conn, err := listener.Accept()
for {
checkError("Error accepting: ", err)
go handleRequest(conn)
}
The application starts goroutines in a loop to read the single connection. The first goroutine to read the connection is successful. The subsequent goroutines report an error.
Change the code to:
for {
conn, err := listener.Accept()
checkError("Error accepting: ", err)
go handleRequest(conn)
}
The client is not sending a newline as expected by the server. Use this command to send the message:
echo "Server test." | nc localhost 5000
You appear to be using echo
incorrectly. The flag -e
interprets the two characters as a newline (check here).
Use the following command to send data to server:
echo -e "Server test.
" | nc localhost 5000
Other than that you should also fix for
loop:
for {
conn, err := listener.Accept()
checkError("Error accepting: ", err)
go handleRequest(conn)
}
In your original code you are only one connection is ever accepted. After that the for loop simply starts more goroutines that try to read on a closed connection (error or not, first handleRequest
call closes the connection).