Only one RPC server allowed per process?

1,735 views
Skip to first unread message

andrew...@gmail.com

unread,
Jan 22, 2014, 12:39:18 AM1/22/14
to golan...@googlegroups.com
I've been prototyping an RPC application using goroutines instead of separate processes. While multiple objects can be registered with RPC then connected to individually, all remote procedure calls are routed to the first object registered. Here is simple code which reproduces the behaviour (with error checking removed - no errors occur):

package main

import (
    "fmt"
    "net"
    "net/rpc"
)

type Server struct {
    id int
}

func (this *Server) Receive(i int, reply *int) error {
    fmt.Println("Server", this.id, "received", i)
    *reply = this.id
    return nil
}

func (this *Server) run(address string) {
    rpc.Register(this)
    ln, _ := net.Listen("tcp", address)
    for {
        cxn, _ := ln.Accept()
        go rpc.ServeConn(cxn)
    }
}

func main() {
    addresses := map[int]string {
        1: "127.0.0.1:10000",
        2: "127.0.0.1:10001",
        3: "127.0.0.1:10002",
    }

    for id, address := range addresses {
        server := Server{id}
        go server.run(address)
    }
    
    servers := make(map[int]*rpc.Client)
    for id, address := range addresses {
        server, _ := rpc.Dial("tcp", address)
        servers[id] = server
    }

    for id, server := range servers {
        var reply int
        server.Call("Server.Receive", id, &reply)
        fmt.Println("Returned", reply)
    }
}

Program output:

Server 1 received 1
Returned 1
Server 1 received 2
Returned 1
Server 1 received 3
Returned 1

All remote procedure calls to Server.Receive are being routed only to the server object with ID 1. Is this expected behaviour? I am running Go 1.2 on Windows 8.1.

Thanks!

Andrew Helwer

Kyle Lemons

unread,
Jan 22, 2014, 1:14:59 PM1/22/14
to andrew...@gmail.com, golang-nuts
You're using the default RPC server when you call rpc.Register, so no, you can't have more than one.

If you want more than one, make separate RPC servers:


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Andrew Helwer

unread,
Jan 22, 2014, 1:44:40 PM1/22/14
to golan...@googlegroups.com, andrew...@gmail.com
Great, thanks! Serves me right for not checking my errors - the second and third calls to rpc.Register return the error "service already defined".

Andrew Helwer

Ross Salas

unread,
Jan 22, 2014, 1:48:37 PM1/22/14
to Kyle Lemons, andrew...@gmail.com, golang-nuts
Also note that I received a panic with the posted code.   There is no guarantee that all the servers are "running" before continuing on the the second for loop where they are Dialed.  Therefore, the first server is being Dialed before it finished Registering.  If I put time.Sleep(2 * time.Second) between the first two for loops, that gives enough time for all servers to fire up and be ready.  You may want to look into better ways of coordinating these actions.  Also,  for your production code, you may want to make sure that all servers are running before continuing on (make sure they didn't error while starting up).

Kyle Lemons

unread,
Jan 22, 2014, 1:59:58 PM1/22/14
to Ross Salas, andrew.helwer, golang-nuts
Check out my response:

It ensures that the listen has completed before the dial.  (bonus points because it also works in the playground when you do this right)
Reply all
Reply to author
Forward
0 new messages