Рассмотрим потоковую передачу сообщений от клиента на сервер.
Сначала в проекте сервера определим следующий файл metanit.proto:
syntax = "proto3"; package metanit; message Request{ string content = 1; } message Response{ string content = 1; } service Messenger{ // клиентская потоковая передача rpc ClientDataStream (stream Request) returns (Response); }
Здесь сервис Messenger определяет метод ClientDataStream, который получает от клиента в потоке сообщения Request, где данные хранятся в свойстве content. А в ответ клиенту возвращается сообщение Response, которое также содержит строковое свойство content. Чтобы указать, что сервер посылает данные в потоке, перед сообщением Request указывается ключевое слово stream.
Далее в проекте сервера определим следующий класс MessengerService:
using Grpc.Core; using Metanit; // пространство имен сервиса MessengerService public class MessengerService : Messenger.MessengerBase { public override async Task<Response> ClientDataStream(IAsyncStreamReader<Request> requestStream, ServerCallContext context) { await foreach(Request request in requestStream.ReadAllAsync()) { Console.WriteLine(request.Content); } Console.WriteLine("Все данные получены..."); return new Response { Content = "все данные получены" }; } }
Метод сервиса в C# принимает два параметра: контекст ServerCallContext и объект IAsyncStreamReader, который типизируется типом запроса (здесь объект Request) и который позволяет считать данные из потока, то есть в примере выше это объект IServerStreamWriter<Response>
Для непосредственного считывания клиентских сообщений у IAsyncStreamReader вызывается метод ReadAllAsync(), который возвращает асинхронный поток и из которого можно извлечь каждое сообшение.
После получения всех сообщений клиента отправляем в ответ объект Response.
Далее в файле Program.cs подключим сервис MessengerService в приложение:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddGrpc(); var app = builder.Build(); // встраиваем MessengerService в обработку запроса app.MapGrpcService<MessengerService>(); app.MapGet("/", () => "Hello World!"); app.Run();
И запустим проект сервера.
Для тестирования сервиса определим проект консольного приложения. Добавим в него из проекта сервера файл metanit.proto. И в проекте консольного клиента в файле Program.cs определим следующий код:
using Grpc.Net.Client; using Metanit; // пространство имен класса Messenger.MessengerClient // данные для отправки string[] messages = { "Привет", "Как дела?", "Че молчишь?", "Ты че, спишь?", "Ну пока" }; // создаем канал для обмена сообщениями с сервером // параметр - адрес сервера gRPC using var channel = GrpcChannel.ForAddress("https://localhost:7229"); // создаем клиент var client = new Messenger.MessengerClient(channel); var call = client.ClientDataStream(); // посылаем каждое сообщение foreach(var message in messages) { await call.RequestStream.WriteAsync(new Request { Content= message }); } // завершаем отправку сообшений в потоке await call.RequestStream.CompleteAsync(); // получаем ответ сервера Response response = await call.ResponseAsync; Console.WriteLine($"Ответ сервера: {response.Content}");
После создания клиента начинаем взаимодействие с сервером:
var call = client.ClientDataStream();
Этот метод возвращает объект Grpc.Core.AsyncClientStreamingCall<Request, Response>
. Его свойство RequestStream представляет поток отправки и
с помощью метода WriteAsync() позволяет отправить на сервер в потоке сообщения:
foreach(var message in messages) { await call.RequestStream.WriteAsync(new Request { Content= message }); }
В данном случае на сервер отправляются все строки из массива messages.
После завершения отправки данных надо закрыть поток методом CompleteAsync()
await call.RequestStream.CompleteAsync();
Вызов этого метода будет уведомлять сервер о том, что отправка сообщений завершена.
После завершения потока отправки мы можем получить ответ сервера с помощью свойства ResponseAsync
:
Response response = await call.ResponseAsync;
Запустим клиент. Клиент отправит серверу все сообщения, и консоль сервера выведет все отправленные сообщения:
Привет Как дела? Че молчишь? Ты че, спишь? Ну пока Все данные получены...