dongse5408 2019-02-28 05:03
浏览 89
已采纳

如何关闭另一个goroutine的读取TCP连接?

My server senario is like this: One io thread is doing read on a tcp connection all the time. After a while the control thread may decide to close it due to low activity or some other reason. If c.Close() is called the io thread will report an error like this: read tcp xxx->xxx: use of closed network connection.

The code is like this:

func recv(c net.Conn) {
    input := bufio.NewScanner(c)
    for input.Scan() {
        msg <- input.Text()
        ...
    }
}

//main
conn, err := s.Accept()
...
go recv(conn)
for {
    select {
    case m := <-msg:
         ...
    case <-timeout:
        conn.Close() // oops!
    }
}

I could ignore the error perhaps but I wonder whether there is a better way.

  • 写回答

3条回答 默认 最新

  • dongtao1262 2019-02-28 05:26
    关注

    The options are to close the connection or set the read deadline to a time in the past. Either way, read on the connection will return an error.

    The simplest approach for handling these errors is to handle all errors returned from read on the network connection uniformly: close the connection, clean up the resources associated with the connection and move on. It's OK to close the connection twice.

    func recv(c net.Conn, msg chan string) {
        defer close(msg) // Notify main goroutine that recv is done.
        defer c.Close()  // Release resources.
    
        input := bufio.NewScanner(c)
    
        // Loop reading lines until read on c returns an error.
        // These errors include io.EOF (normal close by the peer),
        // the error caused by the main goroutine closing the connection
        // and other networking errors.
        for input.Scan() {
            msg <- input.Text()
        }
    }
    
    // main
    
    conn, err := s.Accept()
    if err != nil {
        // handle error
    }
    
    msg := make(chan string)
    go recv(conn, msg)
    
    for {
        select {
        case m, ok := <-msg:
            if !ok {
                // The recv goroutine closed the channel and the connection.
                return
            }
            fmt.Println(m)
        case <-timeout:
            // Closing the connection causes the recv goroutine to break
            // out of the loop. If the recv goroutine received a line of 
            // text and has yet sent the text to the msg channel, then 
            // a return from main at this point will cause the recv goroutine
            // to block forever. To avoid this, continue looping until until
            // the recv goroutine signals that it's done by closing the msg
            // channel.
            conn.Close()
        }
    }
    

    }

    The application can record that it's shutting down the connection and handle read errors after that point in a special way, but only do that if the application needs to do something special in this situation.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)
  • ¥15 AIC3204的示例代码有吗,想用AIC3204测量血氧,找不到相关的代码。