亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何關閉來自另一個 goroutine 的讀取 TCP 連接?

如何關閉來自另一個 goroutine 的讀取 TCP 連接?

Go
九州編程 2023-06-12 15:07:40
我的服務器 senario 是這樣的:一個 io 線程一直在讀取 tcp 連接。一段時間后,控制線程可能會由于活動較少或其他原因而決定關閉它。如果調用 c.Close() io 線程將報告這樣的錯誤:read tcp xxx->xxx: use of closed network connection。代碼是這樣的:func recv(c net.Conn) {    input := bufio.NewScanner(c)    for input.Scan() {        msg <- input.Text()        ...    }}//mainconn, err := s.Accept()...go recv(conn)for {    select {    case m := <-msg:         ...    case <-timeout:        conn.Close() // oops!    }}我也許可以忽略該錯誤,但我想知道是否有更好的方法。
查看完整描述

3 回答

?
拉莫斯之舞

TA貢獻1820條經驗 獲得超10個贊

選項是關閉連接或將讀取截止日期設置為過去的某個時間。無論哪種方式,讀取連接都會返回錯誤。

處理這些錯誤的最簡單方法是統一處理網絡連接上讀取返回的所有錯誤:關閉連接,清理與連接關聯的資源,然后繼續。關閉連接兩次就可以了。

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()

? ? }

}

}

應用程序可以記錄它正在關閉連接并在該點之后以特殊方式處理讀取錯誤,但只有在這種情況下應用程序需要做一些特殊的事情時才這樣做。



查看完整回答
反對 回復 2023-06-12
?
慕沐林林

TA貢獻2016條經驗 獲得超9個贊

有一些錯誤建議單獨處理,例如:


EOF:一條長收到的消息已經讀完,一切正常,繼續。


“一個現有的連接被遠程主機強行關閉”:客戶端關閉應用程序。這是正常的,通話結束,所以返回。


else: 一些 loginc 或服務器錯誤,需要記錄并修復


handler(c net.Conn){

    defer c.Close()

    for {

       ...

       if e!=nil {

            if e == io.EOF{

                continue

            }

            if strings.Contains(e.Error(), "An existing connection was forcibly closed by the remote host.") {

                return

            }

            log.Println(e.Error())

            return

        }

    }

}

在你的情況下,你不想處理包含“使用關閉的網絡連接”的錯誤??梢院雎运⒂涀£P閉循環。否則一些內存會泄漏并且例程掛起。可能有一個隱藏的你忽略一遍又一遍地拋出的錯誤。


查看完整回答
反對 回復 2023-06-12
?
夢里花落0921

TA貢獻1772條經驗 獲得超6個贊

func recv(c *net.Conn) {

    if c == nil {

       return

    }

    input := bufio.NewScanner(*c)

    for input.Scan() {

        msg <- input.Text()

        ...

    }

}


//main

conn, err := s.Accept()

c := &conn

...

go recv(&c)

for {

    select {

    case m := <-msg:

         ...

    case <-timeout:

        conn.Close()

        c = nil

    }

}

不確定這是否是最好的方法。當您關閉 conn 時,您可以將其設置為 nil,而不是從 nil conn 值中讀取。


查看完整回答
反對 回復 2023-06-12
  • 3 回答
  • 0 關注
  • 204 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號