Home > Enterprise >  Golang RCP call hanging
Golang RCP call hanging

Time:06-30

I have a back-end app and a front-end, both in Go. I am trying to make them talk via rpc.

back-end main.go

package main

import (
    "fmt"
    "log"
    "net"
    "net/http"
    "net/rpc"
    "time"
)
type Application struct {
    config struct {
        server struct {
            port    int
            network string
        }
    }
}

type MusicProject struct {
    Id             string
    CreatedTime    time.Time
    LastEditedTime time.Time
    Title          string
    Year           int
    Status         string
    Description    string
    ChoirRollup    string
}

func main() {

    var app Application
    app.config.server.port = 5002
    app.config.server.network = "tcp"

    if err := rpc.Register(new(Application)); err != nil {
        log.Fatal(err)
    }
    rpc.HandleHTTP()

    // start the rpc server
    log.Println("Starting server port", app.config.server.port)
    l, err := net.Listen("tcp", fmt.Sprintf(":%v", app.config.server.port))
    if err != nil {
        log.Fatal(err)
    }
    if err = http.Serve(l, nil); err != nil {
        log.Fatal(err)
    }
}

func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {

    musicProject := MusicProject{
        Id:             id,
        CreatedTime:    time.Now(),
        LastEditedTime: time.Now(),
        Title:          "Test Project",
        Year:           2020,
        Status:         "Completed",
        Description:    "Short project Description",
        ChoirRollup:    "Best Choir",
    }

    model = &musicProject
    return nil
}

front-end rpc call

package main

import (
    "log"
    "net/rpc"
    "time"
)

type MusicProject struct {
    Id             string
    CreatedTime    time.Time
    LastEditedTime time.Time
    Title          string
    Year           int
    Status         string
    Description    string
    ChoirRollup    string
}

func main() {

    dial, err := rpc.Dial("tcp", "localhost:5002")
    if err != nil {
        log.Println(err)
    }

    projectID := "some_id_123"

    var musicProject MusicProject

    err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
    if err != nil {
        log.Println(err)
    }

    log.Println(musicProject)
}

Once the client method is call, the call hanged indefinite with out sending back any error, so quite difficult to debug.

Do you have any suggestion for debugging? Do you see anything wrong in my code? Thank you for your help!

CodePudding user response:

Your server is serving HTTP:

if err = http.Serve(l, nil); err != nil {
   log.Fatal(err)
}

But your client is using straight TCP (HTTP runs over TCP but adds another layer):

err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)

So to fix your issue you need to change one side or the other. For example change the server to:

rpc.Accept(l)

(alternatively you could use rpc.DialHTTP in the client)

There are a couple of other issues with your code (the main one being the way you set the response in the back-end). The following works for me (have not put much effort into making it tidy or testing!).

server

package main

import (
    "fmt"
    "log"
    "net"
    "net/rpc"
    "time"
)

type MusicProject struct {
    Id             string
    CreatedTime    time.Time
    LastEditedTime time.Time
    Title          string
    Year           int
    Status         string
    Description    string
    ChoirRollup    string
}

type Application struct {
}

func (app *Application) GetMusicProjectById(id string, model *MusicProject) error {
    *model = MusicProject{
        Id:             id,
        CreatedTime:    time.Now(),
        LastEditedTime: time.Now(),
        Title:          "Test Project",
        Year:           2020,
        Status:         "Completed",
        Description:    "Short project Description",
        ChoirRollup:    "Best Choir",
    }
    return nil
}

func main() {
    const port = 5002
    if err := rpc.Register(new(Application)); err != nil {
        log.Fatal(err)
    }

    // start the rpc server
    log.Println("Starting server on port:", port)
    l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
    if err != nil {
        log.Fatal(err)
    }
    rpc.Accept(l)
}

client

package main

import (
    "log"
    "net/rpc"
    "time"
)

type MusicProject struct {
    Id             string
    CreatedTime    time.Time
    LastEditedTime time.Time
    Title          string
    Year           int
    Status         string
    Description    string
    ChoirRollup    string
}

func main() {
    dial, err := rpc.Dial("tcp", "localhost:5002")
    if err != nil {
        log.Fatal(err)
    }

    projectID := "some_id_123"

    var musicProject MusicProject

    err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
    if err != nil {
        log.Fatal("error:", err)
    }
    log.Println(musicProject)
}
  • Related