dongyishe6689 2019-07-30 19:28
浏览 753
已采纳

通过特定端口发送GRPC通信

I am running a GRPC server (Server A) listening on a specific port. I want to be able to send a communication to another server (Server B), and have Server B record the incoming address of Server A's connection so that it may later contact Server A.

On Server A, I listen on a port and create a context like such:

lis, err := net.Listen("tcp", "0.0.0.0:6000")
ctx, cancel := context.WithTimeout(context.Background(),
    10000*time.Millisecond)

Then create a connection like so:

connection, err = grpc.DialContext(ctx, server2Address,
grpc.WithInsecure(), grpc.WithBlock())

Before finally sending a message to an endpoint on Server B, which attempts to read the IP address of Server A's incoming connection

info, _ := peer.FromContext(ctx)
fmt.Printf(info.Addr.String()) // Returns a random port, NOT 6000,

However, the resulting port printed by Server B is random, like 62056 as opposed to 6000 as intended. My assumption is that, on Server A, GRPC dials from a random port - is it possible to force GRPC to dial from port 6000 as opposed to a random port?

  • 写回答

1条回答 默认 最新

  • dousa1630 2019-07-30 23:59
    关注

    You can specify the source port like this:

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

    However if your server is listening on the same port this will result in an error:

    panic: dial tcp 127.0.0.1:6000->127.0.0.1:6001: bind: address already in use
    

    A different approach would be to pass the address as metadata. On the client you do:

    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",
    })
    

    And on the server:

    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
    }
    

    And a third approach would be to use streaming.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 数据库原理及应用上机练习题
  • ¥30 征集Python提取PDF文字属性的代码
  • ¥15 如何联系真正的开发者而非公司
  • ¥15 有偿求苍穹外卖环境配置
  • ¥15 代码在keil5里变成了这样怎么办啊,文件图像也变了,
  • ¥20 Ue4.26打包win64bit报错,如何解决?(语言-c++)
  • ¥15 clousx6整点报时指令怎么写
  • ¥30 远程帮我安装软件及库文件
  • ¥15 关于#自动化#的问题:如何通过电脑控制多相机同步拍照或摄影(相机或者摄影模组数量大于60),并将所有采集的照片或视频以一定编码规则存放至规定电脑文件夹内
  • ¥20 深信服vpn-2050这台设备如何配置才能成功联网?