Wednesday, April 22, 2015

Day 5 - IPC using RPC

As RPC is built into Go, lets give it a try.

Im using the rpcbotinterfaceobjects from Day 4 in
$GOPATH\src\github.com\<yourgithubusername>\rpcbotinterfaceobjects

If you dont have rpcbotinterfaceobjects_input.go and rpcbotinterfaceobjects_output.go please check my Day 4 post.

For RPC we need a new struct which connects the in&output structs to the RPC service:

Create a new file rpcservice.go in $GOPATH\src\github.com\<yourgithubusername>\rpcbotinterfaceobjects and copy into it:

package rpcbotinterfaceobjects

import (
    "strconv"
    "strings"
)

type Bot struct {
    ServiceCallCount int
}

// test ProcessPost function - turn the input to uppercase
func (this *Bot) ProcessPost(in *BotInput, out *BotOutput) error {
    out.SetContent(strings.ToUpper(in.GetContent()) + " = " + strconv.Itoa(this.ServiceCallCount))
    this.ServiceCallCount++
    return nil
}



Next is the server:

In $GOPATH\src\github.com\<yourgithubusername>\testrpc create botserver.go:

 package main

import (
    "fmt"
    "github.com/kimxilxyong/rpcbotinterfaceobjects"
    "log"
    "net"
    "net/rpc"
    "os"
    "os/signal"
    "runtime"
)

func init() {
    runtime.GOMAXPROCS(runtime.NumCPU())
}

func main() {

    InstallCtrlCPanic()
    InstallKillPanic()

    bot := new(rpcbotinterfaceobjects.Bot)
    rpc.Register(bot)

    listener, e := net.Listen("tcp", ":9876")
    if e != nil {
        log.Fatal("listen error:", e)
    }

    fmt.Println("Server listening")

    rpc.Accept(listener)
}

// InstallCtrlCPanic installs a Ctrl-C signal handler that panics
func InstallCtrlCPanic() {
    go func() {
        defer SavePanicTrace()
        ch := make(chan os.Signal, 1)
        signal.Notify(ch, os.Interrupt)
        for _ = range ch {
            panic("ctrl-c")
        }
    }()
}

// InstallKillPanic installs a kill signal handler that panics
// From the command-line, this signal is agitated with kill -ABRT
func InstallKillPanic() {
    go func() {
        //defer SavePanicTrace()
        ch := make(chan os.Signal, 1)
        signal.Notify(ch, os.Kill)
        for _ = range ch {
            panic("sigkill")
        }
    }()
}

func SavePanicTrace() {
    r := recover()
    if r == nil {
        return
    }
    // Redirect stderr
    file, err := os.Create("panic")
    if err != nil {
        panic("dumper (no file) " + r.(fmt.Stringer).String())
    }

    //syscall.Dup2(int(file.Fd()), int(os.Stderr.Fd()))
    defer func() { file.Close() }()
    panic("dumper " + r.(string))
}




Next is the client, in the same folder create: botclient.go

package main

import (
    "fmt"
    "github.com/kimxilxyong/rpcbotinterfaceobjects"
    "log"
    "net/rpc"
)

func main() {

    client, err := rpc.Dial("tcp", "localhost:9876")
    if err != nil {
        log.Fatal("dialing:", err)
    }
    // Synchronous call
    in := rpcbotinterfaceobjects.BotInput{"BotInputTestText"}
    var out rpcbotinterfaceobjects.BotOutput

    err = client.Call("Bot.ProcessPost", in, &out)
    if err != nil {
        log.Fatal("ProcessPost error:", err)
    }
    fmt.Printf("ProcessPost: %s\n", out.GetContent())
}

Now open a Cmd shell and build it:

cd $GOPATH\src\github.com\<yourgithubusername>\testrpc
go build botserver.go
go build botclient.go

First run the server:


Then the client:




No comments:

Post a Comment