7

EDIT: I don't want to use Consul or ZooKeeper. I want to find the address of a web service on a local network.

What are the gRPC equivalents of service discovery classes in WCF, like: ServiceDiscoveryBehavior and UdpDiscoveryEndpoint and DiscoveryClient used in this example:

Service:

using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress))
{
    // Add calculator endpoint
    serviceHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), string.Empty);

    // ** DISCOVERY ** //
    // Make the service discoverable by adding the discovery behavior
    ServiceDiscoveryBehavior discoveryBehavior = new ServiceDiscoveryBehavior();
    serviceHost.Description.Behaviors.Add(discoveryBehavior);

    // Send announcements on UDP multicast transport
    discoveryBehavior.AnnouncementEndpoints.Add(new UdpAnnouncementEndpoint());

    // ** DISCOVERY ** //
    // Add the discovery endpoint that specifies where to publish the services
    serviceHost.Description.Endpoints.Add(new UdpDiscoveryEndpoint());

    // Open the ServiceHost to create listeners and start listening for messages.
    serviceHost.Open();
}

Client:

{
    DiscoveryClient discoveryClient = new DiscoveryClient(new UdpDiscoveryEndpoint());

    Collection<EndpointDiscoveryMetadata> calculatorServices =   
        (Collection<EndpointDiscoveryMetadata>)
        discoveryClient.Find(new FindCriteria(typeof(ICalculator))).Endpoints;

    discoveryClient.Close();

    CalculatorClient client = new CalculatorClient();  
    client.Endpoint.Address = calculatorServices[0].Address;
}  
Jinjinov
  • 2,554
  • 4
  • 26
  • 45
  • 1
    [ASP.NET Core gRPC for WCF developers](https://learn.microsoft.com/en-us/dotnet/architecture/grpc-for-wcf-developers/ws-protocols?WT.mc_id=DT-MVP-5003235): *The WS-Discovery protocol is used to locate services on a local network. gRPC services are generally located using DNS or a service registry such as Consul or ZooKeeper.* – Reza Aghaei Dec 20 '19 at 19:40
  • You can also take a look at this post:[GRPC Service Discovery](https://stackoverflow.com/q/37534274/3110834). – Reza Aghaei Dec 20 '19 at 19:41
  • You may also find [Node.js: Protobuf, gRPC and Discovery Services](https://medium.com/@FloSloot/node-js-protobuf-grpc-and-discovery-services-fd099a3fe51a) useful. – Reza Aghaei Dec 20 '19 at 19:46
  • @RezaAghaei https://stackoverflow.com/questions/37534274/grpc-service-discovery wants to discover what GRPC requests the service is capable of receiving, given the address of a GRPC service. I want to discover the address. – Jinjinov Dec 20 '19 at 21:27

1 Answers1

8

gRPC has no classes equivalent to ServiceDiscoveryBehavior, UdpDiscoveryEndpoint or DiscoveryClient.

You have to use System.Net.Sockets to write your own network discovery using UDP broadcast.

Service:

IPAddress ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList.
                      FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork);

Server grpcServer = new Server
{
    Services = { Simulator.BindService(new Service()) },
    Ports = { new ServerPort(ipAddress.ToString(), 8080, ServerCredentials.Insecure) }
};
grpcServer.Start();

Task.Run(() =>
{
    while (true)
    {
        UdpClient udpServer = new UdpClient(8888);
        IPEndPoint clientEndPoint = new IPEndPoint(IPAddress.Any, 0);
        byte[] clientRequestData = udpServer.Receive(ref clientEndPoint);
        string clientRequest = Encoding.ASCII.GetString(clientRequestData);
        Console.WriteLine($"Recived {clientRequest} from {clientEndPoint.Address}");

        byte[] responseData = Encoding.ASCII.GetBytes("Response");
        udpServer.Send(responseData, responseData.Length, clientEndPoint);
        udpServer.Close();
    }
});

Client:

UdpClient udpClient = new UdpClient { EnableBroadcast = true };
byte[] requestData = Encoding.ASCII.GetBytes("Request");
udpClient.Send(requestData, requestData.Length, new IPEndPoint(IPAddress.Broadcast, 8888));

IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
byte[] serverResponseData = udpClient.Receive(ref serverEndPoint);
string serverResponse = Encoding.ASCII.GetString(serverResponseData);
Console.WriteLine($"Recived {serverResponse} from {serverEndPoint.Address}");

IPAddress ipAddress = serverEndPoint.Address;
udpClient.Close();

var grpcChannel = new Channel(ipAddress.ToString(), 8080, ChannelCredentials.Insecure);
var grpcClient = new Client(grpcChannel);
Jinjinov
  • 2,554
  • 4
  • 26
  • 45
  • 3
    Would you kindly explain the down-vote? A) gRPC library really does not have any such class and B) this code does exactly what the WCF code is doing. – Jinjinov Dec 27 '19 at 14:23