TCP到Redis服务器且通道卡死

时间:2018-09-23 15:01:08

标签: go redis

我需要发送3次echo aaa到Redis服务器, 但它卡在过程的中间,我也检查 如果readwrite操作收到错误消息,但没有。 那么,为什么它卡在过程的中间?

package main



import (
    "fmt"
    "os"
    "io"
    "net"
    "sync"
)

var (
    wg = new(sync.WaitGroup)
)

func readFromServer(isWrite chan bool, r io.Reader) {
    for {
        select {
        case <-isWrite:
            _ , err := io.Copy(os.Stdout, r)
            if err != nil {
                panic(err)
            }
        }
    }
}

func writeToServer(conn net.Conn , isWrite chan bool ){
    defer wg.Done()
    for i :=0; i<3; i++{
        _ , err := conn.Write([]byte("*2\r\n$4\r\necho\r\n$3\r\naaa\r\n"))
        if err != nil {
            panic(err)
        }
        isWrite<- true
    }
}

func main(){
    wg.Add(1)

    conn ,err := net.Dial("tcp","127.0.0.1:6379")
    isWrite := make(chan bool)

    if err != nil {
        panic(err)
    }

    go readFromServer(isWrite, conn)
    go writeToServer(conn , isWrite)



    wg.Wait()
    fmt.Println("finished...")
}

输出:

$3
aaa
$3
aaa
Stuck here...

1 个答案:

答案 0 :(得分:1)

readFromServer函数从isWrite通道接收一个值,然后阻止对io.Copy的调用。 io.Copy函数直到EOF或某些错误读取或写入数据后才返回。所有程序输出均来自对io.Copy的单次调用。

在sendToServer块中第二个发送到isWrite。 isWrite通道是一个无缓冲通道。直到有接收方,才会在无缓冲通道上进行发送。通道上没有接收器,因为对io.Copy的调用中阻止了readFromServer。

可能的解决方法是:

  • 解决方法是修改readFromServer以解析RESP协议,并在循环中每次迭代恰好读取一条消息。

  • 通过一次调用io.Copy替换readFromServer中的循环。

不需要isWrite通道。

程序无法确保readFromServer在程序退出之前从writeToServer读取所有响应。