在RPC调用中确定请求者的IP地址

时间:2012-09-27 21:14:42

标签: go rpc

在Go中使用标准net/rpc功能,我想确定入站RPC请求的IP地址是什么。基础http功能似乎在http.Request对象中提供了此功能,但我看不到从默认RPC处理程序(使用rpc.HandleHTTP设置)获得此功能的任何方法。

是否有一些隐藏机制可以获取基础http.Request,或者我是否需要做一些更好的设置不同的HTTP响应者?

4 个答案:

答案 0 :(得分:4)

据我所知,无法从默认服务器的某个地方获取地址。

调用请求接收函数的service call method不提供对编解码器中存储的远程数据的任何访问。

如果http处理程序可以注册两次(which they can't),则可能会HandleHTTP覆盖HTTP处理程序设置的DefaultRPCPath。但那只是not possible today

您可以做的事情,不用大惊小怪,就是使用您自己的ServeHTTP方法构建基于默认服务器的RPC服务器:

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

type myRPCServer struct {
   *rpc.Server
}

func (r *myRPCServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
   log.Println(req.RemoteAddr)
   r.Server.ServeHTTP(w, req)
}

func (r *myRPCServer) HandleHTTP(rpcPath, debugPath string) {
    http.Handle(rpcPath, r)
}

func main() {
    srv := &myRPCServer{rpc.NewServer()}
    srv.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath)

    // ...http listen code...
}

这样做的缺点当然是你不能再使用rpc.Register了。你必须写srv.Register

修改:我忘记了您还需要编写自己的HandleHTTP。原因是,如果您嵌入RPC服务器并编写srv.HandleHTTP,则会在嵌入式实例上调用它,将嵌入式实例传递给http.Handle(),忽略您自己对ServeHTTP的定义。这样做有一个缺点,即您无法使用调试路径调试RPC服务器,因为服务器的HandleHTTP使用了private debug handlerrpc.debugHTTP),而您无法使用访问。

答案 1 :(得分:1)

net/rpc包的抽象级别高于tcp或http。由于它可以使用多个编解码器,因此它无法提供获取入站rpc的ip地址的方法。从理论上讲,有人可以实现代替unix套接字或使用无线电发射器的代码。

如果要访问传输层的细节,则必须删除堆栈中的级别,并使用netnet/http目录来制作rpc服务。

答案 2 :(得分:1)

您也可以使用https://github.com/valyala/gorpc代替net / rpc,它将客户端地址传递给RPC服务器处理程序 - 有关详细信息,请参阅http://godoc.org/github.com/valyala/gorpc#HandlerFunc

答案 3 :(得分:0)

似乎目前无法在rpc函数中执行此操作。 有关详细信息,请参阅此link

以下是摘要。

问:

  

现在可以调用RemoteAddr()方法来仅获取RPC客户端的地址   net.Conn当客户端拨打服务器时,但假设您的服务器有多个   客户端连接,每个客户端都调用RPC导出方法。在那儿   一种实现方法的方法,用于从RPC内部获取调用者的远程地址   方法

     

func(t * Type)方法(args * Args,reply * string)错误{
         //类似的东西             * reply = Caller.RemoteAddr()。String()
            //谁现在打电话给这个方法?          返回无      }

答:

  

我怀疑。这将需要API更改(不一定是向后不兼容的   但仍有一点重新设计来提供这个。