2.13Server-Sent Events Unidirectional Communication
With the rapid popularity of the artificial intelligence chatbot ChatGPT, the typewriter-effect conversation design simulated in its user interface has left a deep impression on people. This vivid and realistic interactive experience is actually implemented 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, eliminating the need for the client to continuously 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.
Application scenarios of Server-Sent Events:
- Real-time notifications: It can be used to implement real-time message alerts or notification systems, such as new message alerts on social networks or email arrival notifications.
- Data stream updates: For data that needs continuous updates, such as stock prices, weather information, or sports results,
SSEcan provide instant data updates. - Progress reports: When executing long-running tasks, such as file uploads or complex computations,
SSEcan be used to report the progress of the task to the client. - Logs and monitoring: In the development and operations fields,
SSEcan be used to display changes in log files in real time or monitor the health status of systems.
The following example shows how to use Server-Sent Events to obtain data from the server:
await httpRemoteService.ServerSentEventsAsync("https://localhost:7044/HttpRemote/Events" // Action to take 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 take 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 polling response:
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: Event type (stringtype).Data: Message (stringtype).RawLine: Raw message line (stringtype).Id: EventID(stringtype).Retry: Reconnection time (aninttype in milliseconds).CustomFields: Custom field data (IReadOnlyCollection<KeyValuePair<string, string>>type).
You can also listen for events when the connection succeeds and when sending fails:
await httpRemoteService.ServerSentEventsAsync("https://localhost:7044/HttpRemote/Events" // Action to take when data is received , async (data, token) => { Console.WriteLine(data.Data); await Task.CompletedTask; }, builder => builder // Action to take when the connection opens .SetOnOpen(() => { Console.WriteLine("Connected."); }) // Action to take 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 take when data is received , async (data, token) => { Console.WriteLine(data.Data); await Task.CompletedTask; }) // Action to take when the connection opens .SetOnOpen(() => { Console.WriteLine("Connected."); }) // Action to take when the connection fails to open .SetOnError((ex) => { Console.WriteLine("Connection error: " + ex.Message); }), cancellationToken: cancellationToken);Server-Sent Events is particularly suitable for 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 it is used for real-time data updates, progress reports, or a simple notification system, SSE is a choice worth considering.