Introduction
Modern applications often need real-time communication instead of traditional request-response patterns. This is where gRPC streaming becomes extremely powerful. In .NET, gRPC allows you to stream data between client and server efficiently using HTTP/2.
In this article, we will understand how gRPC streaming works and how to implement server-side streaming and bidirectional streaming in .NET step by step.
What is gRPC Streaming?
gRPC streaming allows sending multiple messages over a single connection instead of making multiple HTTP requests.
There are three types of streaming in gRPC:
Server Streaming: Server sends multiple responses to a single client request
Client Streaming: Client sends multiple requests and gets a single response
Bidirectional Streaming: Both client and server send messages continuously
How gRPC Streaming Works Internally
Uses HTTP/2 protocol
Maintains a single persistent connection
Data is sent in frames instead of full requests
Uses Protocol Buffers (Protobuf) for serialization
This makes it faster and more efficient than REST APIs.
Setting up gRPC in .NET
Create a new gRPC project:
dotnet new grpc -n GrpcStreamingDemo
Define Proto File
syntax = "proto3";
option csharp_namespace = "GrpcStreamingDemo";
service StreamService {
rpc GetServerStream (StreamRequest) returns (stream StreamResponse);
rpc BidirectionalStream (stream StreamRequest) returns (stream StreamResponse);
}
message StreamRequest {
string message = 1;
}
message StreamResponse {
string message = 1;
}
Server-Side Streaming Implementation
In server streaming, client sends one request and server sends multiple responses.
Server Code
public class StreamServiceImpl : StreamService.StreamServiceBase
{
public override async Task GetServerStream(
StreamRequest request,
IServerStreamWriter<StreamResponse> responseStream,
ServerCallContext context)
{
for (int i = 1; i <= 5; i++)
{
await responseStream.WriteAsync(new StreamResponse
{
Message = $"Response {i} for {request.Message}"
});
await Task.Delay(1000);
}
}
}
Client Code
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new StreamService.StreamServiceClient(channel);
var response = client.GetServerStream(new StreamRequest { Message = "Hello" });
await foreach (var item in response.ResponseStream.ReadAllAsync())
{
Console.WriteLine(item.Message);
}
Bidirectional Streaming Implementation
In bidirectional streaming, both client and server send messages simultaneously.
Server Code
public override async Task BidirectionalStream(
IAsyncStreamReader<StreamRequest> requestStream,
IServerStreamWriter<StreamResponse> responseStream,
ServerCallContext context)
{
await foreach (var request in requestStream.ReadAllAsync())
{
await responseStream.WriteAsync(new StreamResponse
{
Message = $"Received: {request.Message}"
});
}
}
Client Code
using var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new StreamService.StreamServiceClient(channel);
using var call = client.BidirectionalStream();
var readTask = Task.Run(async () =>
{
await foreach (var response in call.ResponseStream.ReadAllAsync())
{
Console.WriteLine(response.Message);
}
});
for (int i = 1; i <= 5; i++)
{
await call.RequestStream.WriteAsync(new StreamRequest
{
Message = $"Message {i}"
});
await Task.Delay(500);
}
await call.RequestStream.CompleteAsync();
await readTask;
Key Differences: Server vs Bidirectional Streaming
| Feature | Server Streaming | Bidirectional Streaming |
|---|
| Request Flow | Single request | Multiple requests |
| Response Flow | Multiple responses | Multiple responses |
| Communication | One-way | Two-way |
| Complexity | Simple | More complex |
When to Use gRPC Streaming
Real-time dashboards
Chat applications
Live notifications
Data pipelines
Benefits of gRPC Streaming
High performance
Low latency
Efficient network usage
Strongly typed contracts
Conclusion
gRPC streaming in .NET is a powerful feature for building real-time and high-performance applications. Server-side streaming is ideal when the server needs to push updates, while bidirectional streaming is perfect for interactive, real-time communication scenarios like chat or live data feeds.