استدعاءات RPC الأحادية والبث من الخادم
نفّذوا الاستدعاءات الأحادية والبث من جهة الخادم لدفع البيانات من الخادم إلى العميل في الوقت الفعلي.
استدعاءات RPC الأحادية والبث من الخادم درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.
أنواع RPC في gRPC
يدعم gRPC أربعة أنماط لـ RPC: Unary (طلب واستجابة)، وServer Streaming (يرسل العميل طلبًا واحدًا ويرسل الخادم عدة استجابات)، وClient Streaming، وBidirectional Streaming. يغطي هذا الدرس النمطين الأولين.
Unary RPC: النمط الأساسي
يُعد Unary أبسط الأنماط: طلب واحد واستجابة واحدة. ويشبه استدعاء دالة عاديًا، لكنه ينتقل عبر HTTP/2 باستخدام ترميز 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; }تنفيذ Unary RPC
تجاوز الأسلوب الأساسي المُنشأ. ويوفّر ServerCallContext البيانات الوصفية ورمز الإلغاء والمهلة ومعلومات النظير.
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
};
}
}استدعاء Unary RPC من العميل
يوفّر العميل المُنشأ طُرقًا تبدو متزامنة وأخرى غير متزامنة فعليًا. استخدم دائمًا النسخة 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}");البث من الخادم: تعريف Proto
يضيف البث من الخادم الكلمة المفتاحية stream قبل نوع الاستجابة. يرسل الخادم رسائل متعددة عبر الاتصال نفسه قبل إغلاق البث.
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; }تنفيذ البث من الخادم
استخدم IServerStreamWriter<T> لإرسال الرسائل. تُرجع الطريقة كائنًا من نوع Task — اكتب الرسائل حتى الانتهاء، ثم أعد القيمة.
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);
}
}استهلاك بث من الخادم لدى العميل
استخدم await foreach مع ResponseStream.ReadAllAsync() لمعالجة كل رسالة فور وصولها.
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إلغاء بث من الخادم
مرّر CancellationToken عند فتح الاستدعاء لإيقاف البث من جهة العميل. يستقبل الخادم الإلغاء عبر الرمز المميز الخاص به.
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.");
}البيانات الوصفية: ترويسات الطلب والتذييلات
يدعم gRPC البيانات الوصفية، وهي أزواج مفتاح-قيمة تُرسل كترويسات قبل الاستجابة وتذييلات بعدها. استخدمها لرموز المصادقة أو معرّفات التتبّع أو مؤشرات ترقيم الصفحات.
// 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 لعملاء المتصفح
لا يمكن للمتصفحات استخدام gRPC الخام، لأن تذييلات HTTP/2 غير مدعومة. استخدم Grpc.AspNetCore.Web وعميل JavaScript grpc-web أو Grpc.Net.Client.Web في 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 });من الواقع العملي: خدمة بث السجلات
تبث خدمة لتجميع السجلات إدخالات سجلات التطبيقات إلى عملاء المراقبة المتصلين في الوقت الفعلي باستخدام البث من الخادم.
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)
});
}
}
}تحقّق سريعًا
ما الكلمة المفتاحية في ملف .proto التي تشير إلى RPC يستخدم البث من الخادم؟
مراجعة: RPC أحادي الاتجاه والبث من الخادم
أهم النقاط:
- Unary RPC: طلب واحد واستجابة واحدة — وهو النمط الأكثر شيوعًا
- البث من الخادم: طلب واحد ورسائل استجابة متعددة بمرور الوقت
- نفّذ البث من الخادم بالكتابة إلى
IServerStreamWriter<T> - استهلك البث من الخادم باستخدام
await foreachمعReadAllAsync() - استخدم CancellationToken لإيقاف البث بأمان من أي من الجهتين
- يتيح gRPC-Web لعملاء المتصفح استدعاء خدمات gRPC
تعلم C# مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 93
- الدروس
- 346
الأسئلة الشائعة
هل درس «استدعاءات RPC الأحادية والبث من الخادم» مجاني؟
نعم — نص درس «استدعاءات RPC الأحادية والبث من الخادم» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.
ماذا ستتعلم في «استدعاءات RPC الأحادية والبث من الخادم»؟
نفّذوا الاستدعاءات الأحادية والبث من جهة الخادم لدفع البيانات من الخادم إلى العميل في الوقت الفعلي. تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟
لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «استدعاءات RPC الأحادية والبث من الخادم»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟
نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات gRPC وProtobuf
- استدعاءات RPC الأحادية والبث من الخادم
- البث من العميل والبث ثنائي الاتجاه
- المهل الزمنية والإلغاء والمعترضات