go rpc例項------1. 基於tcp/gob. 2. 基於http/gob. 3. tcp/jsonrpc
阿新 • • 發佈:2018-12-13
前面玩過grpc, 要安裝grpc庫,要安裝protobuf庫等,好多庫啊 。通訊協議是tcp, 採用protobuf序列化。
下面來看看go原生的rpc(不需要安裝一些雜七雜八的庫): 1. 基於tcp/gob. 2. 基於http/gob. 3. tcp/jsonrpc. 其中,1和2採用了gob序列化, 有侷限性,而 3採用的是json序列化,比較通用。
1. 基於tcp/gob
server.go:
package main import ( "net" "log" "net/rpc" ) type Params struct { Width, Height int; } type Rect struct{} // 1. 方法名Area必須大寫 // 2. 必須有兩個引數,且引數必須是外部能訪問的型別或內建型別,且第二個引數必須是指標型別 // 3. 返回值必須是error型別 func (r *Rect) Area(p Params, ret *int) error { *ret = p.Width * p.Height return nil } func main() { rect := new(Rect) rpc.Register(rect) // 註冊 tcplisten, err := net.Listen("tcp", "0.0.0.0:8888") if err != nil { log.Fatal(err) } for { conn, err := tcplisten.Accept() if err != nil { continue } go rpc.ServeConn(conn) } }
跑起來。
client.go:
package main import ( "net/rpc" "fmt" "log" "time" ) type Params struct { Width int Height int } func main() { rpc, err := rpc.Dial("tcp", "127.0.0.1:8888") if err != nil { log.Fatal(err) } for { ret := 0 err = rpc.Call("Rect.Area", Params{50, 100}, &ret) if err != nil { log.Fatal(err) } fmt.Println(ret) time.Sleep(time.Second) } }
跑起來。客戶端結果為:
5000 5000 5000 5000 5000 如果用tcpdump抓包, 則看不出gob的內容是什麼意思。
2. 基於http/gob:
server.go:
package main import ( "net/http" "log" "net/rpc" ) type Params struct { Width, Height int; } type Rect struct{} // 1. 方法名Area必須大寫 // 2. 必須有兩個引數,且引數必須是外部能訪問的型別或內建型別,且第二個引數必須是指標型別 // 3. 返回值必須是error型別 func (r *Rect) Area(p Params, ret *int) error { *ret = p.Width * p.Height return nil } func main() { rect := new(Rect) rpc.Register(rect) // 註冊 rpc.HandleHTTP(); err := http.ListenAndServe(":8080", nil); if err != nil { log.Fatal(err); } }
跑起來。
client.go:
package main
import (
"net/rpc"
"fmt"
"log"
"time"
)
type Params struct {
Width int
Height int
}
func main() {
rpc, err := rpc.DialHTTP("tcp", "127.0.0.1:8080");
if err != nil {
log.Fatal(err);
}
for {
ret := 0
err = rpc.Call("Rect.Area", Params{50, 100}, &ret)
if err != nil {
log.Fatal(err)
}
fmt.Println(ret)
time.Sleep(time.Second)
}
}
客戶端也跑起來,結果:
5000 5000 5000 5000 5000 5000 5000 5000 5000
如果用tcpdump抓包, 則看不出gob的內容是什麼意思。
3. tcp/jsonrpc
server.go:
package main
import (
"net"
"log"
"net/rpc"
"net/rpc/jsonrpc"
)
type Params struct {
Width, Height int;
}
type Rect struct{}
// 1. 方法名Area必須大寫
// 2. 必須有兩個引數,且引數必須是外部能訪問的型別或內建型別,且第二個引數必須是指標型別
// 3. 返回值必須是error型別
func (r *Rect) Area(p Params, ret *int) error {
*ret = p.Width * p.Height
return nil
}
func main() {
rect := new(Rect)
rpc.Register(rect) // 註冊
tcplisten, err := net.Listen("tcp", "0.0.0.0:8888")
if err != nil {
log.Fatal(err)
}
for {
conn, err := tcplisten.Accept()
if err != nil {
continue
}
go jsonrpc.ServeConn(conn)
}
}
跑起來。
client.go:
package main
import (
"net/rpc/jsonrpc"
"fmt"
"log"
"time"
)
type Params struct {
Width int
Height int
}
func main() {
rpc, err := jsonrpc.Dial("tcp", "127.0.0.1:8888");
if err != nil {
log.Fatal(err);
}
for {
ret := 0
err = rpc.Call("Rect.Area", Params{50, 100}, &ret)
if err != nil {
log.Fatal(err)
}
fmt.Println(ret)
time.Sleep(time.Second)
}
}
跑起來,客戶端結果為:
5000 5000 5000 5000 5000 5000 5000
用tcpdump抓包看看:
11:21:57.620895 IP 127.0.0.1.58698 > 127.0.0.1.8888: Flags [P.], seq 207:276, ack 115, win 12135, options [nop,nop,TS val 534958593 ecr 534957588], length 69
0x0000: 0200 0000 4500 0079 0000 4000 4006 0000 [email protected]@...
0x0010: 7f00 0001 7f00 0001 e54a 22b8 54cc e11f .........J".T...
0x0020: 573c c601 8018 2f67 fe6d 0000 0101 080a W<..../g.m......
0x0030: 1fe2 d201 1fe2 ce14 7b22 6d65 7468 6f64 ........{"method
0x0040: 223a 2252 6563 742e 4172 6561 222c 2270 ":"Rect.Area","p
0x0050: 6172 616d 7322 3a5b 7b22 5769 6474 6822 arams":[{"Width"
0x0060: 3a35 302c 2248 6569 6768 7422 3a31 3030 :50,"Height":100
0x0070: 7d5d 2c22 6964 223a 3532 387d 0a }],"id":528}.
11:21:57.620928 IP 127.0.0.1.8888 > 127.0.0.1.58698: Flags [.], ack 276, win 11622, options [nop,nop,TS val 534958593 ecr 534958593], length 0
0x0000: 0200 0000 4500 0034 0000 4000 4006 0000 [email protected]@...
0x0010: 7f00 0001 7f00 0001 22b8 e54a 573c c601 ........"..JW<..
0x0020: 54cc e164 8010 2d66 fe28 0000 0101 080a T..d..-f.(......
0x0030: 1fe2 d201 1fe2 d201 ........
11:21:57.620935 IP 127.0.0.1.8888 > 127.0.0.1.58698: Flags [.], ack 276, win 11622, options [nop,nop,TS val 534958593 ecr 534958593], length 0
0x0000: 0200 0000 4500 0034 0000 4000 4006 0000 [email protected]@...
0x0010: 7f00 0001 7f00 0001 22b8 e54a 573c c601 ........"..JW<..
0x0020: 54cc e164 8010 2d66 fe28 0000 0101 080a T..d..-f.(......
0x0030: 1fe2 d201 1fe2 d201 ........
11:21:57.621160 IP 127.0.0.1.8888 > 127.0.0.1.58698: Flags [P.], seq 115:153, ack 276, win 11622, options [nop,nop,TS val 534958593 ecr 534958593], length 38
0x0000: 0200 0000 4500 005a 0000 4000 4006 0000 [email protected]@...
0x0010: 7f00 0001 7f00 0001 22b8 e54a 573c c601 ........"..JW<..
0x0020: 54cc e164 8018 2d66 fe4e 0000 0101 080a T..d..-f.N......
0x0030: 1fe2 d201 1fe2 d201 7b22 6964 223a 3532 ........{"id":52
0x0040: 382c 2272 6573 756c 7422 3a35 3030 302c 8,"result":5000,
0x0050: 2265 7272 6f72 223a 6e75 6c6c 7d0a "error":null}.
果然, 使用的是json編碼, 有點意思。
就這樣, 不多說。