Implement sending Server Sent Events in C# (no ASP.NET / MVC / …)

前端 未结 2 1710
小蘑菇
小蘑菇 2021-02-06 12:32

For a project, I need to implement SSE (Server Sent Events) in a C# Application. Although this may sound easy, I\'ve got no clue how to solve this.

As I\'m new to C# (th

相关标签:
2条回答
  • 2021-02-06 13:30

    As for a light-weight server I would go with an OWIN selfhost WebAPI (https://docs.microsoft.com/en-us/aspnet/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web-api).

    A simple server-sent event server action would basically go like:

    public class EventController : ApiController
      {
        public HttpResponseMessage GetEvents(CancellationToken clientDisconnectToken)
        {
          var response = Request.CreateResponse();
          response.Content = new PushStreamContent(async (stream, httpContent, transportContext) =>
          {
            using (var writer = new StreamWriter(stream))
            {
              using (var consumer = new BlockingCollection<string>())
              {
                var eventGeneratorTask = EventGeneratorAsync(consumer, clientDisconnectToken);
                foreach (var @event in consumer.GetConsumingEnumerable(clientDisconnectToken))
                {
                  await writer.WriteLineAsync("data: " + @event);
                  await writer.WriteLineAsync();
                  await writer.FlushAsync();
                }
                await eventGeneratorTask;
              }
            }
          }, "text/event-stream");
          return response;
        }
    
        private async Task EventGeneratorAsync(BlockingCollection<string> producer, CancellationToken cancellationToken)
        {
          try
          {
            while (!cancellationToken.IsCancellationRequested)
            {
              producer.Add(DateTime.Now.ToString(), cancellationToken);
              await Task.Delay(1000, cancellationToken).ConfigureAwait(false);
            }
          }
          finally
          {
            producer.CompleteAdding();
          }
        }
      }
    

    The important part here is the PushStreamContent, which basically just sends the HTTP headers and then leaves the connection open to write the data when it is available.

    In my example the events are generated in an extra-task which is given a producer-consumer collection and adds the events (here the current time every second) if they are available to the collection. Whenever a new event arrives GetConsumingEnumerable is automatically notified. The new event is then written in the proper server-sent event format to the stream and flushed. In practice you would need to send some pseudo-ping events every minute or so, as streams which are left open for a long time without data being sent over them would be closed by the OS/framework.

    The sample client code to test this would go like:

    Write the following code in async method.

    using (var client = new HttpClient())
    {
      using (var stream = await client.GetStreamAsync("http://localhost:9000/api/event"))
      {
        using (var reader = new StreamReader(stream))
        {
          while (true)
          {
            Console.WriteLine(reader.ReadLine());
          }
        }
      }
    }
    
    0 讨论(0)
  • 2021-02-06 13:36

    This sounds like a good fit for SignalR. Note SignalR is part of the ASP.NET family, however this does NOT require the ASP.NET framework (System.Web), or IIS, as mentioned in comments.

    To clarify, SignalR is part of ASP.NET. According to their site:

    ASP.NET is an open source web framework for building modern web apps and services with .NET. ASP.NET creates websites based on HTML5, CSS, and JavaScript that are simple, fast, and can scale to millions of users.

    SignalR has no hard dependency on System.Web or on IIS.

    You can self-host your ASP.Net application (see https://docs.microsoft.com/en-us/aspnet/signalr/overview/deployment/tutorial-signalr-self-host). If you use .net core, it is actually self-hosted by default and runs as a normal console application.

    0 讨论(0)
提交回复
热议问题