为了账号安全,请及时绑定邮箱和手机立即绑定

通道卡住的 TCP 到 Redis 服务器

通道卡住的 TCP 到 Redis 服务器

Go
慕容森 2023-04-10 10:41:51
我需要echo aaa向redis服务器发送三次,但它卡在了进程中间,我也检查了是否read和write操作得到错误消息,但它没有。那么,为什么它会卡在进程中间呢?package mainimport (    "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...")}输出:$3aaa$3aaaStuck here...
查看完整描述

1 回答

?
慕妹3146593

TA贡献1820条经验 获得超9个赞

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

第二次发送到 isWrite 在 sendToServer 块中。isWrite 通道是一个无缓冲通道。在没有接收方之前,无缓冲通道上的发送不会继续。通道上没有接收者,因为 readFromServer 在调用 io.Copy 时被阻塞。

可能的修复是:

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

  • 将 readFromServer 中的 for 循环替换为对 io.Copy 的单个调用。

不需要 isWrite 通道。

该程序不确保 readFromServer 在程序退出之前读取来自 writeToServer 的所有响应。


查看完整回答
反对 回复 2023-04-10
  • 1 回答
  • 0 关注
  • 88 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信