TCP Accept and Go 同時実行モデル
Go 同時実行モデルは、ゴルーチン間の通信にチャネルの使用を重視します。ただし、Go で TCP リスナーを操作する場合、net.TCPListener.Accept() メソッドは接続が受け入れられるまで現在のゴルーチンをブロックし、Go 同時実行パラダイムと矛盾しているように見えます。
適切な選択とブロック オプション
システムの呼び出し呼び出しとは異なり、Accept() には適切な選択サポートやサーバー ソケットのブロック オプションを設定する機能がありません。これにより、開発者は次の回避策に頼らざるを得なくなります:
<code class="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, .... } } }()</code>
このパターンでは、select を使用して Accept() を他のチャネルと多重化できますが、リッスンされるソケットごとに個別の goroutine が導入されます。
これは正しい表現ですか?
このアプローチは確かに有効であり、Go 同時実行モデルに従っています。 goroutine は軽量で安価であるため、ソケット リスニング用に複数の goroutine を作成することは一般に許容されます。
代替アプローチ
タイムアウトを伴う選択の実装など、より高度な要件の場合、新しい接続をチャネルにプッシュし、タイマーで多重化できます。
<code class="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 newConns <- nil return } newConns <- c } }(listener) for { select { case c := <-newConns: // new connection or nil if acceptor is down case <-time.After(time.Minute): // timeout branch } }</code>
このアプローチにより、選択とタイムアウトの動作をより詳細に制御できます。
結論として、Accept は() メソッド ブロックであっても、Go 同時実行モデル内に収まります。どのアプローチを選択するかは、アプリケーションの特定の要件とパフォーマンスに関する考慮事項によって異なります。
以上がGo 同時実行での TCP Accepts の処理: 専用の Goroutine を使用するのが最良のアプローチですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。