0Pricing
C# Academy · Lektion

Unäre und serverseitige Streaming-RPCs

Implementieren Sie unäre Aufrufe und serverseitiges Streaming, um Daten in Echtzeit vom Server zum Client zu übertragen.

Unäre und serverseitige Streaming-RPCs ist eine kostenlose C# Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C# Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

gRPC-RPC-Typen

gRPC unterstützt vier RPC-Muster: unär (Anfrage/Antwort), Server-Streaming (der Client sendet eine Anfrage, der Server mehrere), Client-Streaming und bidirektionales Streaming. Diese Lektion behandelt die ersten beiden.

Unäres RPC: Das grundlegende Muster

Ein unäres RPC ist das einfachste Muster – eine Anfrage, eine Antwort. Es sieht wie ein gewöhnlicher Funktionsaufruf aus, wird aber über HTTP/2 mit Protobuf-Codierung übertragen.

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

Ein unäres RPC implementieren

Überschreiben Sie die generierte Basismethode. ServerCallContext stellt Metadaten, ein Abbruchtoken, eine Deadline und Peer-Informationen bereit.

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

Einen unären RPC vom Client aus aufrufen

Der generierte Client stellt sowohl synchron wirkende als auch tatsächlich asynchrone Methoden bereit. Verwenden Sie in der Produktion immer die Variante Async.

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

Server-Streaming: Proto-Definition

Beim Server-Streaming steht das Schlüsselwort stream vor dem Antworttyp. Der Server sendet mehrere Nachrichten über dieselbe Verbindung, bevor er den Stream schließt.

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

Server-Streaming implementieren

Verwenden Sie IServerStreamWriter<T>, um Nachrichten zu senden. Die Methode gibt ein Task zurück – schreiben Sie, bis alle Nachrichten gesendet sind, und geben Sie dann zurück.

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

Einen Server-Stream auf dem Client verarbeiten

Verwenden Sie await foreach mit ResponseStream.ReadAllAsync(), um jede Nachricht zu verarbeiten, sobald sie eintrifft.

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

Einen Server-Stream abbrechen

Übergeben Sie beim Öffnen des Aufrufs ein CancellationToken, um den Stream auf der Clientseite zu beenden. Der Server empfängt die Abbruchanforderung über sein eigenes 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.");
}

Metadaten: Request-Header und Trailer

gRPC unterstützt Metadaten (Schlüssel-Wert-Paare), die als Header vor der Antwort und als Trailer nach der Antwort gesendet werden. Verwenden Sie sie für Authentifizierungstoken, Tracing-IDs oder Paginierungs-Cursor.

// 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 Browser-Clients

Browser können kein direktes gRPC verwenden (HTTP/2-Trailer werden nicht unterstützt). Verwenden Sie Grpc.AspNetCore.Web und den grpc-web-JavaScript-Client oder 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 });

Praxisbeispiel: Dienst zum Streamen von Protokollen

Ein Protokollaggregationsdienst streamt mithilfe von Server-Streaming Anwendungseinträge in Echtzeit an verbundene Überwachungsclients.

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

Kurze Prüfung

Welches Schlüsselwort in einer .proto-Datei kennzeichnet einen Server-Streaming-RPC?

Zusammenfassung: Unäre und Server-Streaming-RPCs

Wichtige Erkenntnisse:

  • Unärer RPC: eine Anfrage, eine Antwort – das häufigste Muster
  • Server-Streaming: eine Anfrage, mehrere Antwortnachrichten im Zeitverlauf
  • Implementieren Sie Server-Streaming, indem Sie in IServerStreamWriter<T> schreiben
  • Verarbeiten Sie Server-Streams mit await foreach auf ReadAllAsync()
  • Verwenden Sie CancellationToken, um Streams von beiden Seiten sauber zu beenden
  • Mit gRPC-Web können Browser-Clients gRPC-Dienste aufrufen

Häufig gestellte Fragen

Ist die Lektion „Unäre und serverseitige Streaming-RPCs“ kostenlos?

Ja — der vollständige Text von „Unäre und serverseitige Streaming-RPCs“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C# Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C# Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Unäre und serverseitige Streaming-RPCs“?

Implementieren Sie unäre Aufrufe und serverseitiges Streaming, um Daten in Echtzeit vom Server zum Client zu übertragen. Du übst C# Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um C# Academy zu starten?

Keine Vorkenntnisse erforderlich. C# Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.

Wie lange dauert die Lektion „Unäre und serverseitige Streaming-RPCs“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser C# Academy-Lektion Code schreiben und ausführen?

Ja. Jede C# Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Grundlagen von gRPC und Protobuf
  2. Unäre und serverseitige Streaming-RPCs
  3. Client- und bidirektionales Streaming
  4. Deadlines, Abbruch und Interceptors
← Zurück zu C# Academy