Jump bufio.Scanner stops while reading TCP connection from Redis
Reading TCP connection between Redis server using bufio.Scanner
fmt.Fprintf(conn, "*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nHello!!\r\n")
scanner := bufio.NewScanner(conn)
for {
// fmt.Println("marker00")
if ok := scanner.Scan(); !ok {
// fmt.Println("marker01")
break
}
// fmt.Println("marker02")
fmt.Println(scanner.Text())
}
"+ OK" appears in the result for the first scan, but the second scan only stops when the method is called Scan
. (marker00 → marker02 → marker00 and don't display anymore)
Why does it stop Scan
and how do I know the end of a TCP response (no use bufio.Reader
)?
Redis does not close the connection for you after sending the command. Scan () ends after io.EOF, which is not sent.
Check it:
package main
import (
"bufio"
"fmt"
"net"
)
// before go run, you must hit `redis-server` to wake redis up
func main() {
conn, _ := net.Dial("tcp", "localhost:6379")
message := "*3\r\n$3\r\nSET\r\n$1\r\na\r\n$1\r\nb\r\n"
go func(conn net.Conn) {
for i := 0; i < 10; i++ {
fmt.Fprintf(conn, message)
}
}(conn)
scanner := bufio.NewScanner(conn)
for {
if ok := scanner.Scan(); !ok {
break
}
fmt.Println(scanner.Text())
}
fmt.Println("Scanning ended")
}
Old question, but I had the same problem. Two solutions:
1) Add "QUIT \ r \ n" command to your Redis post. This will force Redis to close the connection, which will stop scanning. You have to deal with the extra "+ OK" that quit prints.
2) Add
conn.SetReadDeadline(time.Now().Add(time.Second*5))
just before scanning. This will make the scan stop trying after 5 seconds. Unfortunately, it always takes 5 seconds to complete a scan, so choose this time wisely.