6.33Server-Sent Events Unidirectional Communication

Created on Aug 17, 2026~8 min read

With the rapid rise in popularity of the AI chatbot ChatGPT, the typewriter-effect conversation design in its user interface left a deep impression. This vivid, lifelike interactive experience is actually achieved through a technology called "Server-Sent Events" (Server-Sent Events, SSE).

Server-Sent Events is a communication technology that allows the server to proactively send real-time update data to the client (usually a browser). Unlike the traditional client-request / server-response pattern, SSE implements unidirectional, asynchronous communication from the server to the client, thereby eliminating the need for the client to continually poll the server for the latest data. This technology greatly reduces the burden on the server and improves the efficiency and real-time nature of data transmission.

Use cases for Server-Sent Events:

  1. Real-time notifications: It can be used to implement real-time message alerts or notification systems, such as new-message prompts on social networks or email arrival notifications.
  2. Data stream updates: For data that needs to be continuously updated, such as stock prices, weather information, or sports results, SSE can provide instant data updates.
  3. Progress reporting: When executing long-running tasks, such as file uploads or complex computations, SSE can be used to report task progress to the client.
  4. Logs and monitoring: In the development and operations domains, SSE can be used to display changes in log files in real time or to monitor the health status of systems.

The following example shows how to use Server-Sent Events to retrieve data from the server:

cs
await httpRemoteService.ServerSentEventsAsync("https://localhost:7044/HttpRemote/Events"   // Action to perform when data is received   , async (data, token) =>   {       Console.WriteLine(data.Data);       await Task.CompletedTask;   }, cancellationToken: cancellationToken);// Using the builder patternawait httpRemoteService.SendAsync(HttpRequestBuilder   .ServerSentEvents("https://localhost:7044/HttpRemote/Events"   // Action to perform when data is received   , async (data, token) =>   {       Console.WriteLine(data.Data);       await Task.CompletedTask;   }), cancellationToken: cancellationToken);

Server-Sent Events also supports consuming data as IAsyncEnumerable<ServerSentEventsData>, allowing you to use await foreach to iterate over each polled response:

cs
await foreach (var data in httpRemoteService.ServerSentEventsAsAsyncEnumerable("https://localhost:7044/HttpRemote/Events", cancellationToken: cancellationToken)){    Console.WriteLine(data.Data);}// Using the builder patternawait foreach (var data in httpRemoteService.SendAsAsyncEnumerable(HttpRequestBuilder.ServerSentEvents("https://localhost:7044/HttpRemote/Events"), cancellationToken)){    Console.WriteLine(data.Data);}

The data parameter is of type ServerSentEventsData, which contains the following properties:

  • Properties:
    • Event: The event type (of type string).
    • Data: The message (of type string).
    • RawLine: The raw message line (of type string).
    • Id: The event ID (of type string).
    • Retry: The reconnection interval (of type int, in milliseconds).
    • CustomFields: Custom field data (of type IReadOnlyCollection<KeyValuePair<string, string>>).

You can also listen for the events that fire when the connection opens and when an error occurs:

cs
await httpRemoteService.ServerSentEventsAsync("https://localhost:7044/HttpRemote/Events"   // Action to perform when data is received   , async (data, token) =>   {       Console.WriteLine(data.Data);       await Task.CompletedTask;   }, builder => builder   // Action when the connection is opened   .SetOnOpen(() =>   {       Console.WriteLine("Connected.");   })   // Action when the connection fails to open   .SetOnError((ex) =>   {       Console.WriteLine("Connection error: " + ex.Message);   }), cancellationToken: cancellationToken);// Using the builder patternawait httpRemoteService.SendAsync(HttpRequestBuilder   .ServerSentEvents("https://localhost:7044/HttpRemote/Events"   // Action to perform when data is received   , async (data, token) =>   {       Console.WriteLine(data.Data);       await Task.CompletedTask;   })   // Action when the connection is opened   .SetOnOpen(() =>   {       Console.WriteLine("Connected.");   })   // Action when the connection fails to open   .SetOnError((ex) =>   {       Console.WriteLine("Connection error: " + ex.Message);   }), cancellationToken: cancellationToken);

Server-Sent Events is especially well suited to scenarios where the server needs to send updates to the client but the client does not need to send requests to the server frequently. Whether for updating data in real time, providing progress reports, or implementing a simple notification system, SSE is a choice worth considering.