0

概述

我正在编写一个程序,其中在一个 goroutine 中启动服务器。服务器有几个不同的 goroutine :

  1. 主协程:它处理初始化,启动第二个协程来监听新的连接(2),然后进入一个无限循环来处理从连接(即客户端)接收到的数据。
  2. 监听 goroutine:这个 goroutine 进入一个无限循环,不断地监听新的连接。如果一个新的连接被接受,另一个 goroutine 被启动,它监听来自连接的消息,直到它被关闭。

服务器似乎运行良好。我可以成功添加许多新连接,并且在这些新连接最初被服务器接受后,我还可以在这些新连接上发送数据。

我的客户很简单。还有两个 goroutine:

  1. 主 goroutine:它处理初始化,向服务器注册客户端,启动第二个 goroutine 以从服务器读取数据 (2),然后进入无限循环以对从服务器接收到的数据进行操作。
  2. 第二个 goroutine:这个 goroutine 不断尝试从服务器读取数据,直到连接关闭。

饥饿

我在客户端的 goroutine 饥饿问题上遇到了很大的问题。具体来说,客户端的第二个 goroutine 总是饿死。这是饥饿的 goroutine 的来源:

func receiver() {
    for {
        msg, err := bufio.NewReader(conn).ReadString(byte(protocol.EndOfMessage))
        if err != nil {
            fmt.Printf("Disconnected from server %v.\n", conn.RemoteAddr())
            return
        }
        if len(msg) < 2 {
            continue
        }
        receiverToHandler <- msg[1 : len(msg)-1]
    }
}

我确信一条消息正在从服务器发送到客户端。我也确信正在发送的消息以protocol.EndOfMessage. 我也确信我从服务器获取数据的方法是正确的,因为我使用相同的代码来注册客户端,而不是在无限循环中运行它,我允许它预先指定的尝试次数。

由于某种原因,我的客户不会收到数据。

为了确定我没有误解 goroutines 的性质,如果我用以下代码替换上面的代码:

func receiver() {
    for {
        fmt.Println("In the receiver goroutine!")
    }
}

goroutine 完全按预期工作:一切都像以前一样运行,但是“在接收者 goroutine 中!” 不断打印。因此,在这种情况下,例程肯定是正确执行的。

我的处理程序

func handleMessage(debug bool) {
    select {
    case msg := <-receiverToHandler:
        update(msg, debug)
    default:
        /* if debug {
         *     fmt.Printf("Nothing received!\n")
         * }
         */
    }
}

现在,update(msg, debug)只需调用fmt.Println(msg).

我能做些什么来彻底解决这个问题吗?我觉得放弃优先级/强制调度程序运行是解决这个问题的一个 hacky 解决方案。

4

0 回答 0