在JSON-RPC方法中获取websocket连接信息

时间:2015-04-14 19:02:55

标签: go websocket json-rpc

我在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)
}

1 个答案:

答案 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, &params)

但在返回之前,您可以使用一些反射并在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
}

有点笨拙,但我认为你可以做到这一点。