在Go中进行简单的RPC调用

huangapple go评论82阅读模式
英文:

Simple RPC Call in Go

问题

我正在尝试使用Go中的RPC调用来创建一个最小的应用程序。从我的代码中可以看出,我大量借鉴了在线示例

server.go:

package main

import (
	[...]
)

type InfoDumper int

func (s *InfoDumper) Dump(request string, reply *string) error {

	fmt.Println("Woooh imma deliverin stuff\n")

	current_time := time.Now()

	h := sha1.New()
	var barray []byte
	copy(barray, request)
	hash_rq := h.Sum(barray)

	*reply = request + "\n" + current_time.Format(time.ANSIC) + "\n" + string(hash_rq) + "\n"
	return nil
}

func main() {

	server := new(InfoDumper)

	rpc.Register(server)
	rpc.HandleHTTP()

	l, e := net.Listen("tcp", "127.0.0.1:40000")
	if e != nil {
		fmt.Println(e)
	}

	http.Serve(l, nil)

}

client.go:

package main

import (
	[...]
)

func main() {

	client, e := rpc.Dial("tcp", "127.0.0.1:40000")

	if e != nil {
		fmt.Println(e)
	} else {
		fmt.Println("wooh server is ok")
	}

	in := bufio.NewReader(os.Stdin)

	for {

		line, _, _ := in.ReadLine()
		request := string(line)
		var reply string

		e = client.Call("InfoDumper.Dump", request, &reply)

		if e != nil {
			fmt.Println("omg error!", e)
		}

		fmt.Println(reply)
	}

}

我唯一看到的区别是我写的是http.Serve(l, nil)而不是go http.Serve(l, nil);这是因为使用go关键字会导致我的服务器立即终止。
InfoDump应该会回复一个副本,其中包含发送的内容、时间和请求的哈希值。

目前的情况是:

  • 我在一个终端中运行server.go
  • 我在另一个终端中运行client.go,大约一秒钟后会打印出"wooh server is ok"
  • 我在客户端输入一些内容并按Enter键
  • 要么什么都不会发生,要么在客户端打印出"rpc: client protocol error: unexpected EOF"
  • 如果没有发生任何事情,终止服务器(即按下Control-C)会使客户端打印出上述错误

无论哪种情况,"Woooh imma deliverin stuff"都不会显示在服务器端...

这是在课堂上进行的,作为熟悉Go中的RPC的初步步骤,然后再进行更严肃的练习;所有其他学生都设法使这一步骤正常工作,并查看了这段代码,但是他们看不出与他们的代码有什么不同。

有人看到这段代码有什么问题吗?

英文:

I am trying to get a minimal application working using RPC calls in Go. I am heavily borrowing from the online example, as you can see from my code:

server.go:

<!-- language: lang-go -->

package main

import (
	[...]
)

type InfoDumper int

func (s *InfoDumper) Dump(request string, reply *string) error {

	fmt.Println(&quot;Woooh imma deliverin stuff\n&quot;)

	current_time := time.Now()

	h:= sha1.New()
	var barray []byte
	copy(barray, request)
	hash_rq := h.Sum(barray)

	*reply = request + &quot;\n&quot; + current_time.Format(time.ANSIC) + &quot;\n&quot;  + string(hash_rq) + &quot;\n&quot;
	return nil
}


func main() {

	server := new(InfoDumper)

	rpc.Register(server)
	rpc.HandleHTTP()

	l, e := net.Listen(&quot;tcp&quot;, &quot;127.0.0.1:40000&quot;)
	if e != nil {
		fmt.Println(e)
	}

	http.Serve(l, nil)

}

client.go:

<!-- language: lang-go -->

package main

import (
	[...]
)

func main() {

	client, e := rpc.Dial(&quot;tcp&quot;, &quot;127.0.0.1:40000&quot;)

	if e!=nil {
		fmt.Println(e)
	}	else {
		fmt.Println(&quot;wooh server is ok&quot;)
	}

	in:= bufio.NewReader(os.Stdin)

	for {

		line, _, _ := in.ReadLine()
		request := string(line)
		var reply string

		e = client.Call(&quot;InfoDumper.Dump&quot;, request, &amp;reply)

		if (e!=nil) {
			fmt.Println(&quot;omg error!&quot;, e)
		}

		fmt.Println(reply)
	}

}

The only difference I can see is that I wrote http.Serve(l, nil) instead of go http.Serve(l, nil) ; this is because writing with go makes my server terminate right away.
InfoDump is supposed to reply with a copy of whatever was sent, the time and hash of the request.

This is what's happening right now:

  • I run server.go in a terminal
  • I run client.go in another terminal, after a second or so "wooh server is ok" is printed
  • I type something and hit Enter on the client's side
  • either nothing happens, or "rpc: client protocol error: unexpected EOF" is printed on the client's side
  • if nothing happened, terminating the server (ie hitting Control-C) makes the client print the error above

In either case, "Woooh imma deliverin stuff" is never displayed on the server's side...

This was done during class as a preliminary step to get acquainted with RPC in Go before going on to more serious exercises ; all the other students managed to get this step working, looked at this code and couldn't see the difference with theirs.

Does anyone see anything wrong with this code?

答案1

得分: 5

正如我在邮件列表回复中提到的,如果你想连接到使用HandleHTTP提供的RPC服务器,你需要使用DialHTTP

我在邮件列表中还对你的代码做了一些其他的注释(包括样式:使用gofmt和MixedCaps,参考Effective Go,并确保在出现错误时退出)。

英文:

As I noted in my mailing list response, you will need to use DialHTTP if you want to connect to an RPC server that you have served using HandleHTTP.

I've made some other notes about your code (including styling: use gofmt and MixedCaps, per Effective Go, and be sure to bail out on errors) on the mailing list.

huangapple
  • 本文由 发表于 2013年12月5日 01:12:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/20381648.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定