C# Academy · Lektion

Unary- och serverströmmande RPC-anrop

Implementera unary-anrop och serverströmning för att skicka data från server till klient i realtid.

Lektion 2 av 413 steg

Unary- och serverströmmande RPC-anrop är en gratis lektion i C# Academy på CoddyKit. Detta är lektion 2 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för C# Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i C# Academy innehåller totalt 4 lektioner.

gRPC-RPC-typer

gRPC stöder fyra RPC-mönster: Unary (begäran/svar), Server Streaming (klienten skickar en, servern skickar många), Client Streaming och Bidirectional Streaming. Den här lektionen behandlar de två första.

Unary RPC: Det grundläggande mönstret

Unary är det enklaste mönstret – en begäran, ett svar. Det liknar ett vanligt funktionsanrop men skickas via HTTP/2 med Protobuf-kodning.

// .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; }

Implementera en Unary RPC

Åsidosätt den genererade basmetoden. ServerCallContext tillhandahåller metadata, annulleringstoken, tidsgräns och information om motparten.

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

Anropa en unary-RPC från en klient

Den genererade klienten tillhandahåller både metoder som ser synkrona ut och verkligt asynkrona metoder. Använd alltid varianten Async i produktion.

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

Serverströmning: Proto-definition

Serverströmning lägger till nyckelordet stream före svarstypen. Servern skickar flera meddelanden över samma anslutning innan strömmen stängs.

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

Implementera serverströmning

Använd IServerStreamWriter<T> för att skicka meddelanden. Metoden returnerar en Task — skriv tills allt är klart och returnera sedan.

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

Läsa en serverström från klienten

Använd await foreach på ResponseStream.ReadAllAsync() för att behandla varje meddelande när det anländer.

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

Avbryta en serverström

Skicka med en CancellationToken när anropet öppnas för att stoppa strömmen på klientsidan. Servern tar emot avbrytningen via sin egen 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.");
}

Metadata: begärandehuvuden och trailers

gRPC stöder metadata (nyckel-värde-par) som skickas som headers före svaret och trailers efter svaret. Använd dem för autentiseringstokens, spårnings-ID:n eller pagineringsmarkörer.

// 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 för webbläsarklienter

Webbläsare kan inte använda rå gRPC (HTTP/2-trailers stöds inte). Använd Grpc.AspNetCore.Web och JavaScript-klienten grpc-web eller Blazors Grpc.Net.Client.Web.

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

I praktiken: tjänst för loggströmning

En tjänst för loggaggregering strömmar programloggposter till anslutna övervakningsklienter i realtid med hjälp av serverströmning.

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

Snabb kontroll

Vilket nyckelord i en .proto-fil anger en serverströmmande RPC?

Sammanfattning: unary- och serverströmmande RPC:er

Viktiga lärdomar:

  • Unary-RPC: en begäran, ett svar — det vanligaste mönstret
  • Serverströmning: en begäran och flera svarsmeddelanden över tid
  • Implementera serverströmning genom att skriva till IServerStreamWriter<T>
  • Läs serverströmmar med await foreach på ReadAllAsync()
  • Använd CancellationToken för att avsluta strömmar korrekt från endera sidan
  • gRPC-Web gör det möjligt för webbläsarklienter att anropa gRPC-tjänster
Gratis att börja

Lär dig C# med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
93
Lektioner
346

Vanliga frågor

Är lektionen ”Unary- och serverströmmande RPC-anrop” gratis?

Ja – hela texten till ”Unary- och serverströmmande RPC-anrop” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i C# Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i C# Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Unary- och serverströmmande RPC-anrop”?

Implementera unary-anrop och serverströmning för att skicka data från server till klient i realtid. Ni övar på C# Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig C# Academy?

Du behöver inga förkunskaper. Utbildningen i C# Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 2 av 4.

Hur lång tid tar lektionen ”Unary- och serverströmmande RPC-anrop”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här C# Academy-lektionen?

Ja. Varje C# Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Grunderna i gRPC och Protobuf
  2. Unary- och serverströmmande RPC-anrop
  3. Klient- och dubbelriktad strömning
  4. Deadlines, avbrytning och interceptorer
← Tillbaka till C# Academy