我正在运行一个 GRPC 服务器(服务器 A),监听特定端口。我希望能够向另一台服务器(服务器 B)发送通信,并让服务器 B 记录服务器 A 连接的传入地址,以便稍后可以联系服务器 A。
在服务器 A 上,我监听端口并创建如下上下文:
lis, err := net.Listen("tcp", "0.0.0.0:6000")
ctx, cancel := context.WithTimeout(context.Background(),
10000*time.Millisecond)
然后像这样创建连接:
connection, err = grpc.DialContext(ctx, server2Address,
grpc.WithInsecure(), grpc.WithBlock())
最终向服务器 B 上的端点发送消息之前,服务器 B 会尝试读取服务器 A 传入连接的 IP 地址
info, _ := peer.FromContext(ctx)
fmt.Printf(info.Addr.String()) // Returns a random port, NOT 6000,
但是,服务器 B 打印的结果端口是随机的,例如 62056,而不是预期的 6000。我的假设是,在服务器 A 上,GRPC 从随机端口拨号 - 是否可以强制 GRPC 从端口 6000 而不是随机端口拨号?
最佳答案
您可以像这样指定源端口:
cc, err := grpc.Dial("127.0.0.1:6001", grpc.WithInsecure(),
grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
dst, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
return nil, err
}
src := &net.TCPAddr{
IP: net.ParseIP("127.0.0.1"),
Port: 6000,
}
return net.DialTCP("tcp", src, dst)
}))
但是,如果您的服务器正在监听同一端口,则会导致错误:
panic: dial tcp 127.0.0.1:6000->127.0.0.1:6001: bind: address already in use
另一种方法是将地址作为元数据传递。在客户端上,您执行以下操作:
ctx := context.Background()
ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs("address", "127.0.0.1:6000"))
res, err := grpc_health_v1.NewHealthClient(cc).Check(ctx, &grpc_health_v1.HealthCheckRequest{
Service: "test",
})
在服务器上:
func (s *server) Check(ctx context.Context, req *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error) {
if md, ok := metadata.FromIncomingContext(ctx); ok {
addr := md.Get("address")
// addr == "127.0.0.1:6000"
}
return &grpc_health_v1.HealthCheckResponse{
Status: grpc_health_v1.HealthCheckResponse_SERVING,
}, nil
}
第三种方法是使用 streaming .
关于go - 通过特定端口发送 GRPC 通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57278822/