I'm trying to send more than one request to a TCP server in Go but for some reason the second request is never sent, even if it is identical to the first one.
This is the server:
func StartServer(host string) {
l, err := net.Listen("tcp", host)
log.Println("Starting server on:", host)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer l.Close()
log.Println("Server is running...")
for {
// Listen for an incoming connection.
conn, err := l.Accept()
if err != nil {
log.Fatal("Error accepting: ", err.Error())
}
// Handle connections in a new goroutine.
fmt.Println("got a request")
go handleRequest(conn)
}
}
And this is the function in the client that sends the requests to the server:
func (u *User) ConnectToServer(host string, partner string) {
conn, _ := net.Dial("tcp", host)
fmt.Fprintf(conn, "message1
")
fmt.Fprintf(conn, "message2
")
}
EDIT: In the handleRequest function I read the input as follows:
// Handles incoming requests.
func handleRequest(conn net.Conn) {
rec, err := bufio.NewReader(conn).ReadString('
')
if err != nil {
log.Println("Error reading:", err.Error())
}
log.Println("Got message: ", rec)
// Send a response back to person contacting us.
conn.Write([]byte("Message received."))
// conn.Close()
}
Which according to the documentation only takes the first part before the first line break detected so I believe the second message is ignored because of this. How can I read both messages? Should I change the delimiter in the client maybe?
The server should read multiple lines given that the client sends multiple lines. Use bufio.Scanner to read lines:
func handleRequest(conn net.Conn) {
defer conn.Close()
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
fmt.Printf("Got message: %s
", scanner.Bytes())
conn.Write([]byte("Message received."))
}
if err := scanner.Err(); err != nil {
fmt.Printf("error reading connection: %v
", err)
}
}
Some notes about the code:
bufio.Reader
can also be used to read lines, but bufio.Scanner is easier to use.In handleRequest()
, you call ReadString()
on the bufio Reader. Let's look at the docs:
ReadString reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter. If ReadString encounters an error before finding a delimiter, it returns the data read before the error and the error itself (often io.EOF). ReadString returns err != nil if and only if the returned data does not end in delim. For simple uses, a Scanner may be more convenient.
Considering the packets you're sending are terminated by a , you must call
ReadString()
twice on the same reader. You probably want to call ReadString()
in a loop until it returns an error. Make sure to distinguish io.EOF
, then.
Here's a playground with some inspiration. Note: it appears the playground does not allow TCP sockets, so you will have to run this elsewhere.