Golang rpc得到错误的结构变量
Golang rpc get wrong struct variable
- 我在端口号 8000 和 8100 上注册了两个 RPC 服务,它们是
分别是server1和server2。
- 然后我在server1端创建了一个RPC连接,连接的目的地是server2。
- 连接成功后,我调用连接进行远程调用
- 远程调用成功,但是获取远程调用的被调用方端口号时,有时获取到server1的端口号,有时获取到server2的端口号。在我的理解中,远程调用的被调用方是serve2,程序应该returnserver2的端口号。
- 这是什么原因造成的?
我的代码:
package main
import (
"log"
"net"
"net/rpc"
"sync"
)
type RPCServer struct {
port string
clients map[string]rpc.Client
}
type MessageArgs struct {
Sender string
Message string
}
type MessageReply struct {
Receive bool
}
func (rs *RPCServer) SendMessage(args *MessageArgs, reply *MessageReply) error {
log.Printf("current rpc server [%s] Receive Message [%s] from Sender[%s]", rs.port, args.Message, args.Sender)
reply.Receive = true
return nil
}
func (rs *RPCServer) server(wg *sync.WaitGroup) {
l, e := net.Listen("tcp", rs.port)
if e != nil {
log.Fatal("listen error: ", e)
} else {
log.Printf("server start successfully on port %s\n", rs.port)
}
rpc.Register(rs)
// wait for all server construct but not wait for loop
wg.Done()
for {
conn, err := l.Accept()
if err != nil {
log.Fatal("accept error: ", err)
}
go rpc.ServeConn(conn)
}
}
func (rs *RPCServer) connect(port string) {
client, err := rpc.Dial("tcp", port)
if err != nil {
log.Fatal("dialing: ", err)
} else {
log.Printf("[%s] server connect other server [%s] successfully.\n", rs.port, port)
}
rs.clients[port] = *client
}
func main() {
servers := make([]RPCServer, 2)
ports := [2]string{":8000", ":8100"}
for i := range servers {
servers[i].clients = make(map[string]rpc.Client)
servers[i].port = ports[i]
}
// start all rpc server
var wg sync.WaitGroup
for i := 0; i < 2; i++ {
wg.Add(1)
go servers[i].server(&wg)
}
wg.Wait()
servers[0].connect(":8100")
args := &MessageArgs{Message: "Hello", Sender: ":8000"}
reply := &MessageReply{}
clientCall := servers[0].clients[":8100"]
err := clientCall.Call("RPCServer.SendMessage", args, reply)
if err != nil {
log.Fatal(err)
}
}
有时程序的输出是
2021/07/07 14:39:10 server start successfully on port :8000
2021/07/07 14:39:10 server start successfully on port :8100
2021/07/07 14:39:10 [:8000] server connect other server [:8100] successfully.
2021/07/07 14:39:10 current rpc server [:8000] Receive Message [Hello] from Sender[:8000]
有时程序的输出是
2021/07/07 14:39:16 server start successfully on port :8100
2021/07/07 14:39:16 server start successfully on port :8000
2021/07/07 14:39:16 [:8000] server connect other server [:8100] successfully.
2021/07/07 14:39:16 current rpc server [:8100] Receive Message [Hello] from Sender[:8000]
您正在呼叫 rpc.Register(rs)
两次:
- 为您的代码添加错误检查:
err := rpc.Register(rs)
if err != nil {
log.Println(err)
}
你会看到:
rpc: service already defined: RPCServer
因为你运行这里有两个 goroutines:
for i := 0; i < 2; i++ {
wg.Add(1)
go servers[i].server(&wg)
}
然后他们都将使用以下方式注册一个 rpc 服务器:
rpc.Register(rs)
所以其中一个是偶然的真实注册服务器。
由于 运行 goroutine 的时间未知,因此每个 运行
会 变化
只需注册一台服务器。
例如:
go servers[1].server(&wg)
- 代码审查笔记:
rs.clients[port] = *client
包含 sync.Mutex
和:
A Mutex must not be copied after first use.
- 我在端口号 8000 和 8100 上注册了两个 RPC 服务,它们是 分别是server1和server2。
- 然后我在server1端创建了一个RPC连接,连接的目的地是server2。
- 连接成功后,我调用连接进行远程调用
- 远程调用成功,但是获取远程调用的被调用方端口号时,有时获取到server1的端口号,有时获取到server2的端口号。在我的理解中,远程调用的被调用方是serve2,程序应该returnserver2的端口号。
- 这是什么原因造成的?
我的代码:
package main
import (
"log"
"net"
"net/rpc"
"sync"
)
type RPCServer struct {
port string
clients map[string]rpc.Client
}
type MessageArgs struct {
Sender string
Message string
}
type MessageReply struct {
Receive bool
}
func (rs *RPCServer) SendMessage(args *MessageArgs, reply *MessageReply) error {
log.Printf("current rpc server [%s] Receive Message [%s] from Sender[%s]", rs.port, args.Message, args.Sender)
reply.Receive = true
return nil
}
func (rs *RPCServer) server(wg *sync.WaitGroup) {
l, e := net.Listen("tcp", rs.port)
if e != nil {
log.Fatal("listen error: ", e)
} else {
log.Printf("server start successfully on port %s\n", rs.port)
}
rpc.Register(rs)
// wait for all server construct but not wait for loop
wg.Done()
for {
conn, err := l.Accept()
if err != nil {
log.Fatal("accept error: ", err)
}
go rpc.ServeConn(conn)
}
}
func (rs *RPCServer) connect(port string) {
client, err := rpc.Dial("tcp", port)
if err != nil {
log.Fatal("dialing: ", err)
} else {
log.Printf("[%s] server connect other server [%s] successfully.\n", rs.port, port)
}
rs.clients[port] = *client
}
func main() {
servers := make([]RPCServer, 2)
ports := [2]string{":8000", ":8100"}
for i := range servers {
servers[i].clients = make(map[string]rpc.Client)
servers[i].port = ports[i]
}
// start all rpc server
var wg sync.WaitGroup
for i := 0; i < 2; i++ {
wg.Add(1)
go servers[i].server(&wg)
}
wg.Wait()
servers[0].connect(":8100")
args := &MessageArgs{Message: "Hello", Sender: ":8000"}
reply := &MessageReply{}
clientCall := servers[0].clients[":8100"]
err := clientCall.Call("RPCServer.SendMessage", args, reply)
if err != nil {
log.Fatal(err)
}
}
有时程序的输出是
2021/07/07 14:39:10 server start successfully on port :8000
2021/07/07 14:39:10 server start successfully on port :8100
2021/07/07 14:39:10 [:8000] server connect other server [:8100] successfully.
2021/07/07 14:39:10 current rpc server [:8000] Receive Message [Hello] from Sender[:8000]
有时程序的输出是
2021/07/07 14:39:16 server start successfully on port :8100
2021/07/07 14:39:16 server start successfully on port :8000
2021/07/07 14:39:16 [:8000] server connect other server [:8100] successfully.
2021/07/07 14:39:16 current rpc server [:8100] Receive Message [Hello] from Sender[:8000]
您正在呼叫 rpc.Register(rs)
两次:
- 为您的代码添加错误检查:
err := rpc.Register(rs)
if err != nil {
log.Println(err)
}
你会看到:
rpc: service already defined: RPCServer
因为你运行这里有两个 goroutines:
for i := 0; i < 2; i++ {
wg.Add(1)
go servers[i].server(&wg)
}
然后他们都将使用以下方式注册一个 rpc 服务器:
rpc.Register(rs)
所以其中一个是偶然的真实注册服务器。 由于 运行 goroutine 的时间未知,因此每个 运行
会 变化只需注册一台服务器。 例如:
go servers[1].server(&wg)
- 代码审查笔记:
rs.clients[port] = *client
包含 sync.Mutex
和:
A Mutex must not be copied after first use.