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
)?
source to share
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")
}
source to share
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.
source to share