TCP到Redis服务器且通道卡死

I need to send echo aaa three times to redis server, but its get stuck in the middle of process, I also check if read and write operation get error message, but it doesn't. so, why it get stuck in the middle of process?

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
$4
echo
$3
aaa
"))
        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...")
}

Output:

$3
aaa
$3
aaa
Stuck here...

1个回答



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

第二次发送到sendToServer块中的isWrite。
isWrite通道是未缓冲的通道。 直到有接收方,才会在无缓冲通道上进行发送。 频道上没有接收器,因为readFromServer在对io.Copy的调用中被阻止。</ p>

可能的解决方法是:</ p>


  • 解决方法是修改readFromServer以解析RESP协议,并在循环中的每次迭代中准确读取一条消息。 </ p> </ li>

  • 通过一次调用io.Copy替换readFromServer中的循环。</ p> </ li>
    </ ul>

    不需要isWrite通道。 </ p>

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

展开原文

原文

The readFromServer function receives one value from the isWrite channel and then blocks in the call to io.Copy. The io.Copy function does not return until EOF or some error reading or writing data. All of the program output is from the single call to io.Copy.

The second send to isWrite in sendToServer blocks. The isWrite channel is an unbuffered channel. A send on an unbuffered channel does not proceed until there's a receiver. There is no receiver on the channel because readFromServer is blocked in the call to io.Copy.

Possible fixes are:

  • The fix is to modify readFromServer to parse the RESP protocol and read exactly one message per iteration in the loop.

  • Replace for loop in readFromServer with a single call to io.Copy.

The isWrite channel is not needed.

The program does not ensure that readFromServer reads all of the responses from writeToServer before the program exits.

doupingzhi9674
doupingzhi9674 但是,我的代码之前是否可以保证等待读写完成?,我需要一个答案,因为我不熟悉并发编程:)
接近 2 年之前 回复
duanguan1573
duanguan1573 好的,谢谢,我会努力的
接近 2 年之前 回复
donglong2856
donglong2856 怎么样?如果没有解决,可以提供您的代码段吗?
接近 2 年之前 回复
donglinxia1541
donglinxia1541 好的,我待会再检查。 谢谢你的帮助 :)
接近 2 年之前 回复
duan0065626385
duan0065626385 是的,没错。 我只是重构了代码,您可以在这里检查它,我刚刚在程序中添加了isRead通道,以确保程序在退出之前已读取所有写入的响应。 那是对的吗 ?
接近 2 年之前 回复
duanmi1900
duanmi1900 好的,那解决了一个问题:),在writeToServer()例程中,我在写入服务器后添加了time.Sleep(),所以输出结果出现了三遍,但是如果我在写入服务器后不睡觉,代码就会掉线。 time.Sleep()是否让readFromServer()例程可用于打印到os.Stdout?
接近 2 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问