我在Go工作,並且有點新來使用unix套接字。試圖尋找類似的問題,但找不到任何東西,所以如果這已被回答以前道歉。Golang unix套接字:在不同套接字上註冊RPC的相同類型?
我想使用unix套接字來模擬一組測試機器。我正在測試我的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()
}
我希望這同時打印理查德和BENNY在控制檯中Speak()在不同的客戶端上被調用時,而是打印其中一個兩次,看似隨機。有什麼我在這裏失蹤?輸出示例,這次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.
這工作,謝謝!詳細瞭解net/rpc :) – cort
歡迎您! @cort –