質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

1回答

735閲覧

Go:関数外で呼んだRPCクライアントでRPCを実行できない

kkasou

総合スコア1

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

0クリップ

投稿2022/10/01 11:00

前提

golangで下記のようなコードを書いたところ、RPCでサーバー側の関数を実行できず困っています。どうにかして大量のclientを管理したくて下記のようなコードにしたのですが、動いていません。
https://pkg.go.dev/net/rpc からそのまま引っ張ってきたコードは動くのですが、下記コードは動かず、違いがわかりません。
どうして動かないのかご教示いただけると幸いです。

実現したいこと

RPCをマスターしたい
RPCのClientをIPアドレスとポートで管理したい

発生している問題・エラーメッセージ

下はサーバーのmain.goを実行し、クライアントのmain.goを実行したあと数秒待ってからサーバーをinterruptしたときのそれぞれのメッセージです
(サーバー側)

bash

1 2$ go run . 3^Csignal: interrupt

(クライアント側)

bash

1 2$ go run . 3getClient: {127.0.0.1 1234} 4Client created 52022/10/01 19:40:36 arith error:unexpected EOF 6exit status 1

該当のソースコード

サーバー側はGoの公式ページから引用しました。
クライアント側は同様に引用したものを改変しました。
(サーバー側main.go)

Go

1 2package main 3 4import ( 5 "errors" 6 "log" 7 "net" 8 "net/http" 9 "net/rpc" 10) 11 12type Args struct { 13 A, B int 14} 15 16type Quotient struct { 17 Quo, Rem int 18} 19 20type Arith int 21 22func (t *Arith) Multiply(args *Args, reply *int) error { 23 *reply = args.A * args.B 24 return nil 25} 26 27func (t *Arith) Divide(args *Args, quo *Quotient) error { 28 if args.B == 0 { 29 return errors.New("divide by zero") 30 } 31 quo.Quo = args.A / args.B 32 quo.Rem = args.A % args.B 33 return nil 34} 35func main() { 36 arith := new(Arith) 37 rpc.Register(arith) 38 rpc.HandleHTTP() 39 l, e := net.Listen("tcp", "127.0.0.1"+":1234") 40 if e != nil { 41 log.Fatal("listen error:", e) 42 } 43 http.Serve(l, nil) 44} 45

(クライアント側main.go)

Go

1package main 2 3import ( 4 "fmt" 5 "log" 6 "net/rpc" 7) 8 9type Args struct { 10 A, B int 11} 12 13type Quotient struct { 14 Quo, Rem int 15} 16type Addre struct { 17 Ip string 18 Port string 19} 20type Arith int 21 22var ClientList map[Addre]*rpc.Client 23 24func main() { 25 ClientList = make(map[Addre]*rpc.Client) 26 client, err := getClient(Addre{"127.0.0.1", "1234"}) 27 if err != nil { 28 panic(err) 29 } 30 args := Args{7, 8} 31 var reply int 32 err = client.Call("Arith.Multiply", args, &reply) 33 if err != nil { 34 log.Fatal("arith error:", err) 35 } 36 fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply) 37} 38func getClient(query Addre) (client *rpc.Client, err error) { 39 client, isexist := ClientList[query] 40 if isexist { 41 return client, nil 42 } else { 43 fmt.Println("getClient:", query) 44 client, err = rpc.Dial("tcp4", query.Ip+":"+query.Port) 45 fmt.Println("Client created") 46 ClientList[query] = client 47 if err != nil { 48 fmt.Println("Error connecting") 49 return nil, err 50 } 51 return client, nil 52 } 53 54} 55

試したこと

Goのバージョン変更(1.17、1.18)、Goのキャッシュ削除とバイナリファイル再生成、WindowsやMacOS、VM上のUbuntu2つでの実行、getClientのExported化

補足情報(FW/ツールのバージョンなど)

goのバージョン(1.17、1.18でも試しました)

$ go version
go version go1.19.1 linux/amd64

OS(上のエラーメッセージのときはWSL上で実行しましたが、Windows11やMacOS上でもだめでした)

uname -a
Linux DESKTOP-RP77Q7S 5.15.62.1-microsoft-standard-WSL2 #1 SMP Wed Aug 24 22:24:20 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

サンプルコードと異なる点が2点見つかります。

  • clientの「args := Args{7, 8}」は「args := &Args{7, 8}」のはずです。型がミスマッチ。
  • 「rpc.Dial」ではなく「rpc.DialHTTP」を使うべきです。

投稿2022/10/01 12:13

nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kkasou

2022/10/01 23:34

回答ありがとうございました! DialHTTPの部分の違いは数日間気づかなかったです…直したら動きました! 本当に、本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問