0Pricing
C# Academy · Aula

RPCs unários e transmissão pelo servidor

Implemente chamadas unárias e transmissão pelo servidor para enviar dados do servidor ao cliente em tempo real.

RPCs unários e transmissão pelo servidor é uma aula grátis de C# Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C# Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C# Academy inclui 4 aulas no total.

Tipos de RPC do gRPC

O gRPC oferece suporte a quatro padrões de RPC: Unária (solicitação/resposta), Transmissão do Servidor (o cliente envia uma, o servidor envia várias), Transmissão do Cliente e Transmissão Bidirecional. Esta lição aborda os dois primeiros.

RPC Unária: O Padrão Básico

A RPC unária é o padrão mais simples: uma solicitação e uma resposta. Ela se parece com uma chamada de função normal, mas é transportada por HTTP/2 com codificação Protobuf.

// .proto definition
service OrderService {
  rpc GetOrder (GetOrderRequest) returns (OrderResponse);
}

message GetOrderRequest { int32 id = 1; }
message OrderResponse   { int32 id = 1; string status = 2; double total = 3; }

Implementando uma RPC Unária

Substitua o método base gerado. O ServerCallContext fornece metadados, token de cancelamento, prazo limite e informações do par.

public class OrderService : OrderService.OrderServiceBase
{
    private readonly IOrderRepository _repo;
    public OrderService(IOrderRepository repo) => _repo = repo;

    public override async Task<OrderResponse> GetOrder(
        GetOrderRequest request,
        ServerCallContext context)
    {
        var order = await _repo.GetByIdAsync(request.Id, context.CancellationToken);
        if (order is null)
            throw new RpcException(new Status(StatusCode.NotFound, "Order not found"));

        return new OrderResponse
        {
            Id     = order.Id,
            Status = order.Status.ToString(),
            Total  = (double)order.Total
        };
    }
}

Chamando uma RPC unária de um cliente

O cliente gerado fornece métodos com aparência síncrona e métodos verdadeiramente assíncronos. Sempre use a variante Async em produção.

var client = new OrderService.OrderServiceClient(channel);

// Async call with cancellation
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
var reply = await client.GetOrderAsync(
    new GetOrderRequest { Id = 42 },
    cancellationToken: cts.Token);

Console.WriteLine($"Order {reply.Id}: {reply.Status} - ${reply.Total}");

Transmissão pelo servidor: definição do proto

A transmissão pelo servidor adiciona a palavra-chave stream antes do tipo de resposta. O servidor envia várias mensagens pela mesma conexão antes de fechar a transmissão.

service StockService {
  // Client sends one symbol, server streams price updates
  rpc WatchStock (WatchRequest) returns (stream StockUpdate);
}

message WatchRequest  { string symbol = 1; }
message StockUpdate   { string symbol = 1; double price = 2; int64 timestamp = 3; }

Implementando a transmissão pelo servidor

Use IServerStreamWriter<T> para enviar mensagens. O método retorna uma Task — escreva até terminar e, então, retorne.

public override async Task WatchStock(
    WatchRequest request,
    IServerStreamWriter<StockUpdate> responseStream,
    ServerCallContext context)
{
    while (!context.CancellationToken.IsCancellationRequested)
    {
        var price = await _market.GetPriceAsync(request.Symbol);

        await responseStream.WriteAsync(new StockUpdate
        {
            Symbol    = request.Symbol,
            Price     = price,
            Timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()
        });

        await Task.Delay(1000, context.CancellationToken);
    }
}

Consumindo uma transmissão do servidor no cliente

Use await foreach em ResponseStream.ReadAllAsync() para processar cada mensagem à medida que ela chega.

using var call = client.WatchStock(
    new WatchRequest { Symbol = "MSFT" });

await foreach (var update in call.ResponseStream.ReadAllAsync())
{
    Console.WriteLine($"{update.Symbol}: ${update.Price:F2}");
}
// Continues until server closes the stream or client cancels

Cancelando uma transmissão do servidor

Passe um CancellationToken ao abrir a chamada para interromper a transmissão no lado do cliente. O servidor recebe o cancelamento por meio do próprio token.

var cts = new CancellationTokenSource();

// Cancel after 30 seconds
cts.CancelAfter(TimeSpan.FromSeconds(30));

using var call = client.WatchStock(
    new WatchRequest { Symbol = "AAPL" },
    cancellationToken: cts.Token);

try
{
    await foreach (var update in
        call.ResponseStream.ReadAllAsync(cts.Token))
    {
        Console.WriteLine($"Price: {update.Price}");
    }
}
catch (OperationCanceledException)
{
    Console.WriteLine("Stream cancelled.");
}

Metadados: cabeçalhos de solicitação e cabeçalhos finais

O gRPC oferece suporte a metadados (pares de chave e valor) enviados como cabeçalhos antes da resposta e como cabeçalhos finais depois dela. Use-os para tokens de autenticação, identificadores de rastreamento ou cursores de paginação.

// Server: send initial metadata
await context.WriteResponseHeadersAsync(new Metadata
{
    { "x-correlation-id", Guid.NewGuid().ToString() }
});

// Server: set trailing metadata
context.ResponseTrailers.Add("x-total-count", "1500");

// Client: read headers
var headers  = await call.ResponseHeadersAsync;
var trailerId = headers.GetValue("x-correlation-id");

gRPC-Web para clientes de navegador

Os navegadores não podem usar gRPC direto (os cabeçalhos finais do HTTP/2 não são compatíveis). Use Grpc.AspNetCore.Web e o cliente JavaScript grpc-web ou o Grpc.Net.Client.Web do Blazor.

// dotnet add package Grpc.AspNetCore.Web

app.UseGrpcWeb();
app.MapGrpcService<GreeterService>().EnableGrpcWeb();

// Blazor client:
var handler = new GrpcWebHandler(GrpcWebMode.GrpcWeb,
    new HttpClientHandler());
using var channel = GrpcChannel.ForAddress(
    "https://localhost:7042",
    new GrpcChannelOptions { HttpHandler = handler });

Na prática: serviço de transmissão de registros

Um serviço de agregação de registros transmite entradas de registro da aplicação para clientes de monitoramento conectados em tempo real usando a transmissão pelo servidor.

public override async Task StreamLogs(
    LogStreamRequest request,
    IServerStreamWriter<LogEntry> responseStream,
    ServerCallContext context)
{
    await foreach (var log in _logChannel.Reader.ReadAllAsync(
        context.CancellationToken))
    {
        if (log.Level >= request.MinLevel)
        {
            await responseStream.WriteAsync(new LogEntry
            {
                Level   = log.Level.ToString(),
                Message = log.Message,
                Timestamp = Timestamp.FromDateTime(log.Timestamp)
            });
        }
    }
}

Verificação rápida

Qual palavra-chave em um arquivo .proto indica uma RPC de transmissão pelo servidor?

Recapitulação: RPCs unárias e de transmissão pelo servidor

Principais conclusões:

  • RPC unária: uma solicitação e uma resposta — o padrão mais comum
  • Transmissão pelo servidor: uma solicitação e várias mensagens de resposta ao longo do tempo
  • Implemente a transmissão pelo servidor escrevendo em IServerStreamWriter<T>
  • Consuma transmissões do servidor com await foreach em ReadAllAsync()
  • Use CancellationToken para interromper transmissões de forma controlada em qualquer um dos lados
  • O gRPC-Web permite que clientes de navegador chamem serviços gRPC

Perguntas Frequentes

A aula “RPCs unários e transmissão pelo servidor” é grátis?

Sim — o texto completo de “RPCs unários e transmissão pelo servidor” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C# Academy, atualize para CoddyKit PRO. O curso de C# Academy inclui 4 aulas no total.

O que vou aprender em “RPCs unários e transmissão pelo servidor”?

Implemente chamadas unárias e transmissão pelo servidor para enviar dados do servidor ao cliente em tempo real. Você pratica C# Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar C# Academy?

Nenhuma experiência prévia é necessária. C# Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.

Quanto tempo leva a aula “RPCs unários e transmissão pelo servidor”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de C# Academy?

Sim. Cada aula de C# Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Fundamentos de gRPC e Protobuf
  2. RPCs unários e transmissão pelo servidor
  3. Transmissão pelo cliente e bidirecional
  4. Prazos, cancelamento e interceptadores
← Voltar para C# Academy