2013-02-01 74 views
1

我有一个正在侦听TCP连接并将这些通道发送回主循环的去程序。我在做例行程序的原因是让这个监听不阻塞,并且能够同时处理活动连接。从Go通道获取价值

我有一个空的默认情况下,像这样的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 
// ... 
} 

我收到的连接,但它会阻止......我试图缓冲通道为好,但同样的事情发生。我在这里错过了什么?

+3

请参阅[这个问题](http://stackoverflow.com/questions/14633373/how-to-do-nothing-when-no-channel-is-ready-to-beread)为答案。 – thwd

回答

1

有点难以分辨为什么你没有看到基于现有代码的任何连接。您的示例有一个问题,您在select声明中有一个空的default个案,然后我们无法看到此for循环中还发生了什么。您编写它的方式,该循环可能永远不会屈服于调度器。你基本上是在说:“从渠道中获得一件东西,没有一件好东西,重新开始,从渠道中获得一件东西!”,但你永远不会等待。当你做了一些阻止你的goroutine的动作时,该goroutine屈服于调度器。因此,当你以正常的方式阅读频道时,如果没有价值可读,该goroutine被阻止阅读。由于它被阻塞,它也让调度器允许其他的goroutine继续在底层线程上执行。我相当肯定这就是为什么你的select与一个空的default打破;你正在导致该goroutine无限循环到for循环,而没有屈服于调度器。

目前还不清楚pendingConnections的作用是什么,或者它是否需要。

从行为中无法分辨的另一件事是您的checkError函数。例如,它不会继续到for循环的顶部,或保释。

无论如何,它看起来像这是比它需要更复杂。只需要一个将新连接作为一个参数的函数,然后在连接时在新的goroutine中启动它。我总是写这样的:

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

这是多还是少,他们在the documentation做什么。

+1

谢谢你的回答。汤姆指出了另一个有同样问题的问题。添加一个runtime.Gosched()“固定”的问题,但我明白,这可能意味着我的设计很糟糕。 你的例子是OK的,除了那个l.Accept()块。我想继续在同一个循环中进行操作。 – alf