gpt4 book ai didi

Golang unix 套接字 : registering same type for RPC on different sockets?

转载 作者:数据小太阳 更新时间:2023-10-29 03:24:37 25 4
gpt4 key购买 nike

我在 Go 中工作,对使用 unix 套接字有点陌生。尝试搜索类似的问题,但找不到任何内容,如果之前已经回答过,我们深表歉意。

我想用unix sockets模拟一个机器集群进行测试。我正在测试我的 Raft 实现,所以我想在不同的 unix 套接字上注册相同类型的多个对象(一个庞大的结构)。但是看我写的一个简单的例子,效果似乎不是我想要的:为同一个导出方法拨不同的套接字似乎在单个端口上崩溃:

package main

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

type Server struct {
name string
}

type SpeakArgs struct {
}

type SpeakReply struct {
Success bool
}

type AddArgs struct {
A, B int
}

type AddReply struct {
Answer int
Success bool
}

func (s *Server) Add(args *AddArgs, reply *AddReply) error {
reply.Answer = args.A + args.B
reply.Success = true
return nil
}

func (s *Server) Speak(args *SpeakArgs, reply *SpeakReply) error {
fmt.Printf("My name is %v.\n", s.name)
reply.Success = true
return nil
}

func main() {
var wgMain, wgRegister, wgCall sync.WaitGroup
wgMain.Add(3)
wgRegister.Add(2)
wgCall.Add(1)

go func() {
server := &Server{name: "RICHARD"}
rpc.Register(server)
la, e := net.Listen("unix", "/tmp/example1.sock")
if e != nil {
log.Fatal("listen error:", e)
}
wgRegister.Done()
go rpc.Accept(la)
wgCall.Wait()
la.Close()
wgMain.Done()
fmt.Println("Server exited.")
}()

go func() {
server := &Server{name: "BENNY"}
rpc.Register(server)
lb, e := net.Listen("unix", "/tmp/example2.sock")
if e != nil {
log.Fatal("listen error:", e)
}
wgRegister.Done()
go rpc.Accept(lb)
wgCall.Wait()
lb.Close()
wgMain.Done()
fmt.Println("Server exited.")
}()

go func() {
wgRegister.Wait()
oneclient, err1 := rpc.Dial("unix", "/tmp/example1.sock")
twoclient, err2 := rpc.Dial("unix", "/tmp/example2.sock")
if err1 != nil {
log.Fatal("listen error:", err1)
}
if err2 != nil {
log.Fatal("listen error:", err2)
}

addArgs := &AddArgs{1, 2}
addReply := &AddReply{}
speakArgs := &SpeakArgs{}
speakReply := SpeakReply{}
oneclient.Call("Server.Add", addArgs, addReply)
oneclient.Call("Server.Speak", speakArgs, speakReply)
twoclient.Call("Server.Speak", speakArgs, speakReply)

fmt.Printf("Added numbers! %v + %v = %v.\n", addArgs.A, addArgs.B, addReply.Answer)
wgCall.Done()
oneclient.Close()
twoclient.Close()
wgMain.Done()
fmt.Println("Client exited.")
}()
wgMain.Wait()
}

我希望当在不同的客户端上调用 Speak() 时,这会在控制台中同时打印 RICHARD 和 BENNY,但它却打印其中一个两次,看似随机。我在这里缺少什么吗?示例输出,这次RICHARD好像出来了,但有时候是BENNY。

My name is RICHARD.
My name is RICHARD.
Added numbers! 1 + 2 = 3.
Client exited.
Server exited.
Server exited.

编辑:感谢 Pavlo Strokov 的修复!如果未指定,rpc.Register 默认为 DefaultServer,因此两者都在同一 RPC 服务器上注册:更正的方法是调用 rpc.NewServer() 并在该服务器上注册每个服务器一个。

package main

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

type Server struct {
name string
}

type SpeakArgs struct {
}

type SpeakReply struct {
Success bool
}

type AddArgs struct {
A, B int
}

type AddReply struct {
Answer int
Success bool
}

func (s *Server) Add(args *AddArgs, reply *AddReply) error {
reply.Answer = args.A + args.B
reply.Success = true
return nil
}

func (s *Server) Speak(args *SpeakArgs, reply *SpeakReply) error {
fmt.Printf("My name is %v.\n", s.name)
reply.Success = true
return nil
}

func main() {
var wgMain, wgRegister, wgCall sync.WaitGroup
wgMain.Add(3)
wgRegister.Add(2)
wgCall.Add(1)

go func() {
rpcServer := rpc.NewServer()
server := &Server{name: "RICHARD"}
rpcServer.Register(server)
la, e := net.Listen("unix", "/tmp/example1.sock")
if e != nil {
log.Fatal("listen error:", e)
}
wgRegister.Done()
go rpcServer.Accept(la)
wgCall.Wait()
la.Close()
wgMain.Done()
fmt.Println("Server exited.")
}()

go func() {
rpcServer := rpc.NewServer()
server := &Server{name: "BENNY"}
rpcServer.Register(server)
lb, e := net.Listen("unix", "/tmp/example2.sock")
if e != nil {
log.Fatal("listen error:", e)
}
wgRegister.Done()
go rpcServer.Accept(lb)
wgCall.Wait()
lb.Close()
wgMain.Done()
fmt.Println("Server exited.")
}()

go func() {
wgRegister.Wait()
oneclient, err1 := rpc.Dial("unix", "/tmp/example1.sock")
twoclient, err2 := rpc.Dial("unix", "/tmp/example2.sock")
if err1 != nil {
log.Fatal("listen error:", err1)
}
if err2 != nil {
log.Fatal("listen error:", err2)
}

addArgs := &AddArgs{1, 2}
addReply := &AddReply{}
speakArgs := &SpeakArgs{}
speakReply := &SpeakReply{}
oneclient.Call("Server.Add", addArgs, addReply)
oneclient.Call("Server.Speak", speakArgs, speakReply)
twoclient.Call("Server.Speak", speakArgs, speakReply)

fmt.Printf("Added numbers! %v + %v = %v.\n", addArgs.A, addArgs.B, addReply.Answer)
wgCall.Done()
oneclient.Close()
twoclient.Close()
wgMain.Done()
fmt.Println("Client exited.")
}()
wgMain.Wait()
}

打印

My name is RICHARD.
My name is BENNY.
Added numbers! 1 + 2 = 3.
Client exited.
Server exited.
Server exited.

最佳答案

我认为这是因为您正在使用 DefaultServer 作为您的 RPC 服务器。相反,您应该为每个服务器创建不同的服务器:RICHARD 和 BENNY。请查看我修改后的代码以按预期工作:RPC calls on one machine

关于Golang unix 套接字 : registering same type for RPC on different sockets?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45377224/

25 4 0
文章推荐: go - 设置另一个进程的终端大小(ala `stty columns`)?
文章推荐: jquery - 如何通过 Ajax 发送多个数据字段?
文章推荐: jquery - 使用 val() 函数设置