Go bufio.Scanner在读取Redis的TCP连接时停止。

huangapple go评论82阅读模式
英文:

Go bufio.Scanner stops while reading TCP connection to Redis

问题

使用bufio.Scanner读取Redis服务器之间的TCP连接

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 {
    if ok := scanner.Scan(); !ok {
        break
    }
    fmt.Println(scanner.Text())
}

第一次扫描的结果是"+OK",但第二次扫描在调用Scan方法时停止了(marker00 -> marker02 -> marker00,之后没有输出了)。

为什么Scan会停止,而且如何在不使用bufio.Reader的情况下知道TCP响应的结束?

英文:

Reading TCP connection between Redis-server by using bufio.Scanner

<!-- language: go -->

fmt.Fprintf(conn, &quot;*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nHello!!\r\n&quot;)
scanner := bufio.NewScanner(conn)
for {
    // fmt.Println(&quot;marker00&quot;)
    if ok := scanner.Scan(); !ok {
        // fmt.Println(&quot;marker01&quot;)
        break
    }
    // fmt.Println(&quot;marker02&quot;)
    fmt.Println(scanner.Text())
}

"+OK" comes as the result for first scanning, but the second scanning stops just in invoking Scan method. (marker00 -> marker02 -> marker00 and no output any more)

Why does Scan stop and how can I know the end of TCP response (without using bufio.Reader)?

答案1

得分: 5

Redis在发送命令后不会自动关闭连接。Scan()在未发送io.EOF时结束。

请查看以下代码:

package main

import (
    "bufio"
    "fmt"
    "net"
)

// 在运行之前,你需要启动`redis-server`来唤醒Redis
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("扫描结束")
}

希望对你有帮助!

英文:

Redis does not close the connection for you after sending a command. Scan() ends after io.EOF which is not sent.

Check out this:

package main

import (
    &quot;bufio&quot;
    &quot;fmt&quot;
    &quot;net&quot;
)

// before go run, you must hit `redis-server` to wake redis up
func main() {
    conn, _ := net.Dial(&quot;tcp&quot;, &quot;localhost:6379&quot;)
    message := &quot;*3\r\n$3\r\nSET\r\n$1\r\na\r\n$1\r\nb\r\n&quot;

    go func(conn net.Conn) {
        for i := 0; i &lt; 10; i++ {
            fmt.Fprintf(conn, message)
        }
    }(conn)

    scanner := bufio.NewScanner(conn)
    for {
        if ok := scanner.Scan(); !ok {
            break
        }
        fmt.Println(scanner.Text())
    }
    fmt.Println(&quot;Scanning ended&quot;)
}

答案2

得分: 0

旧问题,但我遇到了同样的问题。有两种解决方案:

1)在你的Redis消息中添加一个"QUIT\r\n"命令。这将导致Redis关闭连接,从而终止扫描。你需要处理额外的" +OK"输出。

2)在开始扫描之前添加conn.SetReadDeadline(time.Now().Add(time.Second*5))。这将导致扫描在5秒后停止尝试。不幸的是,完成扫描始终需要5秒,所以要明智地选择这个时间。

英文:

Old question, but I had the same issue. Two solutions:

  1. Add a "QUIT\r\n" command to your Redis message. This will cause Redis to close the connection which will terminate the scan. You'll have to deal with the extra "+OK" that the quit outputs.

  2. Add

conn.SetReadDeadline(time.Now().Add(time.Second*5))

just before you start scanning. This will cause the scan to stop trying after 5 seconds. Unfortunately, it will always take 5 seconds to complete the scan so choose this time wisely.

huangapple
  • 本文由 发表于 2014年8月24日 14:44:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/25469196.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定