通道卡住的 TCP 到 Redis 服务器

我需要echo aaa向redis服务器发送三次,但它卡在了进程中间,我也检查了是否read和write操作得到错误消息,但它没有。那么,为什么它会卡在进程中间呢?


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...


慕容森
浏览 110回答 1
1回答

慕妹3146593

readFromServer 函数从 isWrite 通道接收一个值,然后阻塞对 io.Copy 的调用。io.Copy 函数直到 EOF 或读取或写入数据时出现错误才会返回。所有程序输出都来自对 io.Copy 的单次调用。第二次发送到 isWrite 在 sendToServer 块中。isWrite 通道是一个无缓冲通道。在没有接收方之前,无缓冲通道上的发送不会继续。通道上没有接收者,因为 readFromServer 在调用 io.Copy 时被阻塞。可能的修复是:修复方法是修改 readFromServer 以解析 RESP 协议并在循环中每次迭代只读取一条消息。将 readFromServer 中的 for 循环替换为对 io.Copy 的单个调用。不需要 isWrite 通道。该程序不确保 readFromServer 在程序退出之前读取来自 writeToServer 的所有响应。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go