C# Academy · Leçon

RPC unaires et flux du serveur

Implémentez des appels unaires et un flux côté serveur pour pousser des données du serveur vers le client en temps réel.

Leçon 2 sur 413 étapes

RPC unaires et flux du serveur est une leçon C# Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C# Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C# Academy comprend 4 leçons au total.

Types de RPC gRPC

gRPC prend en charge quatre modèles RPC : unaire (requête/réponse), diffusion en continu côté serveur (le client envoie une requête et le serveur envoie plusieurs réponses), diffusion en continu côté client et diffusion en continu bidirectionnelle. Cette leçon couvre les deux premiers.

RPC unaire : le modèle de base

Le modèle unaire est le plus simple : une requête, une réponse. Il ressemble à un appel de fonction ordinaire, mais est transmis via HTTP/2 avec un encodage 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; }

Implémenter un RPC unaire

Redéfinissez la méthode de base générée. ServerCallContext fournit les métadonnées, le jeton d’annulation, l’échéance et les informations sur le pair.

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

Appeler un RPC unaire depuis un client

Le client généré fournit des méthodes qui ressemblent à des appels synchrones ainsi que de véritables méthodes async. Utilisez toujours la variante Async en production.

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

Flux serveur : définition du fichier proto

Le flux serveur ajoute le mot-clé stream avant le type de réponse. Le serveur envoie plusieurs messages sur la même connexion avant de fermer le flux.

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

Implémenter un flux serveur

Utilisez IServerStreamWriter<T> pour envoyer des messages. La méthode renvoie une Task — écrivez jusqu’à ce que ce soit terminé, puis retournez.

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

Consommer un flux serveur depuis le client

Utilisez await foreach sur ResponseStream.ReadAllAsync() pour traiter chaque message à mesure de son arrivée.

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

Annuler un flux serveur

Transmettez un CancellationToken lors de l’ouverture de l’appel pour arrêter le flux côté client. Le serveur reçoit l’annulation via son propre jeton.

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

Métadonnées : en-têtes de requête et en-têtes de fin

gRPC prend en charge les métadonnées (paires clé-valeur) envoyées sous forme d’en-têtes avant la réponse et d’en-têtes de fin après celle-ci. Utilisez-les pour les jetons d’authentification, les identifiants de traçage ou les curseurs de pagination.

// 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 pour les clients de navigateur

Les navigateurs ne peuvent pas utiliser gRPC brut (les en-têtes de fin HTTP/2 ne sont pas pris en charge). Utilisez Grpc.AspNetCore.Web et le client JavaScript grpc-web, ou le Grpc.Net.Client.Web de 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 });

Cas concret : service de diffusion de journaux

Un service d’agrégation des journaux diffuse en temps réel les entrées de journal de l’application aux clients de surveillance connectés, grâce au flux serveur.

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

Vérification rapide

Quel mot-clé dans un fichier .proto indique un RPC avec flux serveur ?

Récapitulatif : RPC unaires et flux serveur

Points clés à retenir :

  • RPC unaire : une requête, une réponse — le modèle le plus courant
  • Flux serveur : une requête, plusieurs messages de réponse au fil du temps
  • Implémentez le flux serveur en écrivant dans IServerStreamWriter<T>
  • Consommez les flux serveur avec await foreach sur ReadAllAsync()
  • Utilisez CancellationToken pour arrêter proprement les flux depuis l’un ou l’autre côté
  • gRPC-Web permet aux clients de navigateur d’appeler des services gRPC
Gratuit pour commencer

Apprends C# avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
93
Leçons
346

Questions Fréquemment Posées

La leçon « RPC unaires et flux du serveur » est-elle gratuite ?

Oui — le texte complet de « RPC unaires et flux du serveur » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C# Academy, passe à CoddyKit PRO. Le cours C# Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « RPC unaires et flux du serveur » ?

Implémentez des appels unaires et un flux côté serveur pour pousser des données du serveur vers le client en temps réel. Tu pratiques C# Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer C# Academy ?

Aucune expérience préalable n'est requise. C# Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « RPC unaires et flux du serveur » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon C# Academy ?

Oui. Chaque leçon C# Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Fondamentaux de gRPC et Protobuf
  2. RPC unaires et flux du serveur
  3. Flux du client et flux bidirectionnels
  4. Échéances, annulation et intercepteurs
← Retour à C# Academy