1

TCP 接続をリッスンする go-routine があり、これらをチャネルでメイン ループに送り返します。go-routine でこれを行っている理由は、このリッスンをノンブロッキングにし、アクティブな接続を同時に処理できるようにするためです。

これを、次のようなデフォルトのケースが空の select ステートメントで実装しました。

go pollTcpConnections(listener, rawConnections)

for {
    // Check for new connections (non-blocking)
    select {
    case tcpConn := <-rawConnections:
        currentCon := NewClientConnection()
        pendingConnections.PushBack(currentCon)
        fmt.Println(currentCon)
        go currentCon.Routine(tcpConn)
    default:
    }
   // ... handle active connections
}

これが私の pollTcpConnections ルーチンです。

func pollTcpConnections(listener net.Listener, rawConnections chan net.Conn) {
  for {
    conn, err := listener.Accept()  // this blocks, afaik
    if(err != nil) {
        checkError(err)
    }
    fmt.Println("New connection")
    rawConnections<-conn
  }
}

問題は、これらの接続をまったく受信しないことです。次のように、ブロックする方法でそれを行う場合:

for {
    tcpConn := <-rawConnections
// ...
}

接続を受信しますが、ブロックされます... チャネルもバッファリングしようとしましたが、同じことが起こります。ここで何が欠けていますか?

4

1 に答える 1

1

既存のコードに基づいて接続が表示されない理由を判断するのは少し難しいです。サンプルの問題の1つは、ステートメントに空のdefaultケースがありselect、これで他に何が起こっているのかがわからないことです。forループ。あなたがそれを書いた方法では、そのループはスケジューラーに決して譲らないかもしれません。基本的には「チャンネルから物を入手します。持っていませんか?OK、最初からやり直します。チャンネルから物を入手します!」と言っていますが、実際に待つことはありません。ゴルーチンをブロックするアクションを実行すると、そのゴルーチンはスケジューラーに譲ります。したがって、通常の方法でチャネル読み取りを行う場合、読み取る値がない場合、そのゴルーチンは読み取りをブロックされます。ブロックされているため、他のgoroutineが基になるスレッドで実行を継続できるようにスケジューラーにも譲ります。私はこれがselect空のあなたdefaultが壊れている理由であるとかなり確信しています。あなたはそのゴルーチンをスケジューラーに屈することなくループ上で無限にforループさせています。

の役割が何であるpendingConnectionsか、またはそれがまったく必要かどうかは明らかではありません。

checkError動作から判断することが不可能なもう1つのことは、関数が何をするかです。たとえば、forループの先頭に移動したり、保釈したりすることはありません。

とにかく、これは必要以上に複雑なようです。新しい接続を1つのパラメーターとして受け取る関数を用意し、接続時に新しいゴルーチンでそれを起動するだけです。私はいつもこのように書いています:

func handleConnection(c net.Conn) {
    // do something with your connection here.
}

for {
    // Wait for a connection.
    conn, err := l.Accept()
    if err != nil {
        // do something with your error.  You probably want to break or return here.
        break
    }
    // handle each connection in a new goroutine
    go handleConnection(conn)
}

これは、多かれ少なかれ、ドキュメントで行われていることとまったく同じです。

于 2013-02-01T15:55:03.947 に答える