在Go中使用标准net/rpc
功能,我想确定入站RPC请求的IP地址是什么。基础http
功能似乎在http.Request
对象中提供了此功能,但我看不到从默认RPC处理程序(使用rpc.HandleHTTP
设置)获得此功能的任何方法。
是否有一些隐藏机制可以获取基础http.Request
,或者我是否需要做一些更好的设置不同的HTTP响应者?
答案 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 handler(rpc.debugHTTP
),而您无法使用访问。
答案 1 :(得分:1)
net/rpc
包的抽象级别高于tcp或http。由于它可以使用多个编解码器,因此它无法提供获取入站rpc的ip地址的方法。从理论上讲,有人可以实现代替unix套接字或使用无线电发射器的代码。
如果要访问传输层的细节,则必须删除堆栈中的级别,并使用net
或net/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更改(不一定是向后不兼容的 但仍有一点重新设计来提供这个。