英文:
Golang RCP call hanging
问题
我有一个后端应用程序和一个前端应用程序,都是用Go语言编写的。我正在尝试通过rpc使它们进行通信。
后端的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()
// 启动rpc服务器
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
}
前端的rpc调用部分如下:
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)
}
当调用客户端方法时,调用会无限期地挂起,而不会返回任何错误,因此很难进行调试。
你有任何调试建议吗?你在我的代码中看到了什么问题吗?
谢谢你的帮助!
英文:
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!
答案1
得分: 0
你的服务器正在提供HTTP服务:
if err = http.Serve(l, nil); err != nil {
log.Fatal(err)
}
但是你的客户端正在使用直接的TCP连接(HTTP在TCP上运行,但添加了另一层):
err = dial.Call("Application.GetMusicProjectById", projectID, &musicProject)
所以要解决你的问题,你需要改变其中一方。例如,将服务器改为:
rpc.Accept(l)
(或者你可以在客户端使用rpc.DialHTTP
)
你的代码还有一些其他问题(主要问题是在后端设置响应的方式)。以下是我测试通过的代码(没有花太多精力来整理或测试!)。
服务器
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)
}
// 启动RPC服务器
log.Println("在端口上启动服务器:", port)
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
log.Fatal(err)
}
rpc.Accept(l)
}
客户端
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("错误:", err)
}
log.Println(musicProject)
}
英文:
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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论