Jono
Jono

Reputation: 3633

Trouble with Go Routines and its concurrency

TL;DR accepting and connecting two separate SETS of connections. Want to do it with RPC concurrently.

I'm attempting to create semi distributed system on my computer. The piece of the code I'm working on right now is something like a broker node, in other words it is always accepting client connections from a port. Its also constantly accepting back end node connections from a different port. I'm trying to find a way to concurrently listen for both, and serve both. I'm using RPC and the way I tried doing it is this: Main:

func main(){  
 ...  
 rpc.Register(myInterface)  
 l, err := net.Listen("tcp", client_port)  
 if err != nil {...}  
 go handleClients(l)  
 node_l, err := net.Listen("tcp", node_port)  
 if err != nil{...}   
 go setUpIncomingNodes(node_l, chan)  
 for{// add nodes to a list from chan} 
}

Concurrent functions:

// Adds clients to be connected
func handleClients(listener net.Listener){
 for{
  conn, err :=listener.Accept()
  if err != nil{...}
  // Starts up a blocking (on that thread) RPC connection
  go rpc.serveConn(conn)
 }
}
func setUpIncomingNodes(node_listener net.Listener, incoming_nodes chan<- net.Conn){
 for{
  conn, err := node_listener.Accept()
  if err != nil{...}
  incoming_nodes <- conn     
 }
}

The issue is that it doesn't serve the first node, until the second comes along. I can't understand why. Also it seems that only one connection can happen at time, but I thought RPC served on a different port (thus not blocking it). Any help is super appreciated.

I tried following this tutorial but I found the circumstance too different, its also using a different version of Go. I use two types of nodes/connections where Type A needs to be served through the broker to Type B.

Upvotes: 2

Views: 408

Answers (1)

Jono
Jono

Reputation: 3633

In the end, I think the issue was that I was attempting to pass in listeners to the Go routine, thus having each go routine having a dependancy with the main thread. The working solution ended up being as simple as this:

func main(){
 ...
 node_ip_port := "127.0.0.1:9000"
 client_ip_port := "127.0.0.1:1000"
 nodeChan := make(chan net.Conn, 20)

 go func(ip_port string, nodeChan chan<- net.Conn) {
    l, err := net.Listen("tcp", node_ip)
    if err != nil {
        log.Fatal("Had an error connecting to node", err)
    }
    for {
        conn, _ := l.Accept()
        kvChan <- conn
    }
  }(node_ip_port, nodeChan)

 go func(ip_port string) {
    l, err := net.Listen("tcp", ip_port)
    if err != nil {
        log.Fatal("Had an error connecting to client", err)
    }
    for {
        conn, _ := l.Accept()
        go rpc.ServeConn(conn)
    }
  }(client_ip_port)
  // List of connected nodes
  nodeList := list.New()
  for {
    node := <-nodeChan
    nodeList.PushBack(node)
    // My RPC functions use the nodes in this list to serve :-)
  }
 }

Upvotes: 1

Related Questions