1. 程式人生 > >go rpc例項------1. 基於tcp/gob. 2. 基於http/gob. 3. tcp/jsonrpc

go rpc例項------1. 基於tcp/gob. 2. 基於http/gob. 3. tcp/jsonrpc

      前面玩過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編碼, 有點意思。

         就這樣, 不多說。