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

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

TCP 接受和 Go 并發模型

TCP 接受和 Go 并發模型

Go
海綿寶寶撒 2021-10-04 10:17:01
看著net.TCPListener。考慮到 Go 并發范式,人們會期望將這個系統功能實現為通道,以便您chan *net.Conn從Listen()函數或類似的東西中獲得 a 。但似乎 Accept() 是一種方式,它只是阻塞,就像系統接受一樣。除了它癱瘓了,因為:沒有合適的 select() 可以與它一起使用,因為 go 更喜歡頻道無法為服務器套接字設置阻塞選項。所以我正在做類似的事情:    acceptChannel = make(chan *Connection)    go func() {      for {       rw, err := listener.Accept()       if err != nil { ... handle error ... close(acceptChannel) ... return }       s.acceptChannel <-&Connection{tcpConn: rw, .... }      }    }()這樣我就可以在一個選擇中使用多個服務器套接字,或者將 Accept() 上的等待與其他通道復用。我錯過了什么嗎?我是 Go 的新手,所以我可能會忽略一些事情 - 但是 Go 真的沒有用自己的并發范式實現自己的阻塞系統功能嗎?我真的需要為我想聽的每個套接字(可能是數百個或數千個)單獨的 goroutine 嗎?這是要使用的正確習語,還是有更好的方法?
查看完整描述

1 回答

?
暮色呼如

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

你的代碼很好。您甚至可以更進一步并替換:


s.acceptChannel <-&Connection{tcpConn: rw, .... }

和:


go handleConnection(&Connection{tcpConn: rw, .... })

正如評論中提到的,例程不是系統線程,它們是由 Go 運行時管理的輕量級線程。當您為每個連接創建一個例程時,您可以輕松地使用更容易實現的阻塞操作。Go 運行時然后為您選擇例程,因此您正在尋找的行為只是其他地方,埋在語言中。你看不到它,但它無處不在。


現在,如果您需要更復雜的東西,并且根據我們的對話,實現類似于帶有超時選擇的東西,您將完全按照您的建議執行:將所有新連接推送到一個通道并使用計時器對其進行多路復用。這似乎是 Go 的方式。


請注意,如果您中的一個接受者失敗,則您無法關閉接受通道,因為另一個接受者在寫入時會感到恐慌。


我的(更完整的)示例:


newConns := make(chan net.Conn)


// For every listener spawn the following routine

go func(l net.Listener) {

    for {

        c, err := l.Accept()

        if err != nil {

            // handle error (and then for example indicate acceptor is down)

            newConns <- nil

            return

        }

        newConns <- c

    }

}(listener)


for {

    select {

    case c := <-newConns:

        // new connection or nil if acceptor is down, in which case we should

        // do something (respawn, stop when everyone is down or just explode)

    case <-time.After(time.Minute):

        // timeout branch, no connection for a minute

    }

}


查看完整回答
反對 回復 2021-10-04
  • 1 回答
  • 0 關注
  • 201 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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