Перейти к содержанию

Двунаправленный поток

Каждый из участников взаимодействия отправляет свои сообщения в потоковом режиме, это может происходить параллельно, что означает, что порядок, в котором отправляются сообщения от клиента и от сервера, отсутствует. Клиент инициирует удалённый вызов процедуры с помощью указания имени метода и метаданных. Затем сервер может немедленно ответить возвратом статуса и метаданных (или же может это сделать, когда клиент отправит все свои сообщения).

Диаграмма

sequenceDiagram
participant C as gRPC Client
participant S as gRPC Server
C->>S: Имя метода + метаданные
S->>C: Сообщение ответа 1
C->>S: Сообщение запроса 1
S->>C: Сообщение ответа 2
S->>C: Сообщение ответа 3
S->>C: Сообщение ответа (response message) + gRPC-статус + метаданные

Protobuf

rpc DuplexStreamingFunction (stream InputMessage) returns (stream OutputMessage) {}

Реализация на сервере

Приведём пример, в котором сперва читаются все сообщения клиентского потока, а затем отправляются сообщения серверного потока. Однако, легко придумать пример, когда сообщения потока отправляются асинхронно или в ответ н какое-либо сообщение с клиента.

public override async Task DuplexStreamingFunction(
    IAsyncStreamReader<InputMessage> requestStream,
    IServerStreamWriter<OutputMessage> responseStream,
    ServerCallContext context)
{
    // итерируемся по клиентским сообщениям
    await foreach (var createRequest in requestStream.ReadAllAsync())
    {
        // реализация обработки
    }
    // итерируемся по IEnumerable<OutputMessage> или IAsyncEnumerable<OutputMessage>
    foreach (var outputMessage in outputMessageEnumerable)
    {
        await responseStream.WriteAsync(outputMessage);
    }
}

Использование на клиенте

Также приведём пример, в котором сперва отправляем все клиентские сообщения, а затем получаем все серверные сообщения.

using var duplexStreamingCall = client.DuplexStreamingFunction();
// итерируемся по IEnumerable<InputMessage> или IAsyncEnumerable<InputMessage>
foreach (var inputMessage in inputMessageEnumerable)
{
    await duplexStreamingCall.RequestStream.WriteAsync(request);
}
// Сообщаем серверу о завершении передачи
await duplexStreamingCall.RequestStream.CompleteAsync();
// Читаем поток с сервера
await foreach (var OutputMessage in duplexStreamingCall.ResponseStream.ReadAllAsync())
{
    // обработка переданных сообщений
}

Ссылки

Диаграммы всех видов взаимодействия
примеры Protobuf
Примеры реализаций на сервере
Пример клиента


Последнее обновление : 23 апреля 2023 г.
Дата создания : 23 апреля 2023 г.

Комментарии

Комментарии