我在Websocket上使用JSON-RPC。并且,在RPC方法(比如下面的示例中的Multiply)中,我需要知道哪个连接称为此方法。下面的部分说明" //这里需要Websocket连接信息"。我该怎么做?
package main
import (
"code.google.com/p/go.net/websocket"
"net/http"
"net/rpc"
"net/rpc/jsonrpc"
)
type Args struct {
A int
B int
}
type Arith int
func (t *Arith) Multiply(args *Args, reply *int) error {
*reply = args.A * args.B
// Need Websocket connection information here
return nil
}
func main() {
rpc.Register(new(Arith))
http.Handle("/conn", websocket.Handler(serve))
http.ListenAndServe("localhost:7000", nil)
}
func serve(ws *websocket.Conn) {
jsonrpc.ServeConn(ws)
}
答案 0 :(得分:0)
这将具有挑战性,因为它违反了RPC提供的抽象。这是一个战略建议:
Google为许多API使用了上下文对象:https://blog.golang.org/context。该接口的一部分是任意数据的Value方法:
Value(key interface{}) interface{}
这将为您提供类似线程本地存储的功能,通常在其他编程语言中用于此目的。
那么如何在请求中添加上下文对象?一种方法是创建一个新的自定义ServerCodec
:
type ServerCodec interface {
ReadRequestHeader(*Request) error
ReadRequestBody(interface{}) error
// WriteResponse must be safe for concurrent use by multiple goroutines.
WriteResponse(*Response, interface{}) error
Close() error
}
您的实施主要可以反映jsonrpc
:
var params [1]interface{}
params[0] = x
return json.Unmarshal(*c.req.Params, ¶ms)
但在返回之前,您可以使用一些反射并在params
中查找名称/类型为Context
的字段,然后填充它。类似的东西:
ctx := createContextSomehow()
v := reflect.ValueOf(x)
if v.Kind() == reflect.Ptr {
v = v.Elem()
if v.Kind() == reflect.Struct {
ctxv := v.FieldByName("Context")
ctxv.Set(ctx)
}
}
然后更改您的请求:
type Args struct {
A int
B int
}
将其更改为:
type Args struct {
A int
B int
Context context.Context
}
有点笨拙,但我认为你可以做到这一点。