在ASP.NET Core中保持连接的活动状态

时间:2016-11-03 02:26:45

标签: asp.net-core video-streaming asp.net-core-mvc asp.net-core-webapi

我正在制作一个基于ASP.NET Core构建的小型Web应用程序。我的应用程序是通过服务将视频从客户端传输到客户端。

我已经关注了这篇文章:

http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/

我已经成功实现了教程的应用程序,但是,这是用于将视频从服务器流式传输到客户端。

我现在要做的是:

  • 客户注册服务以进行流式传输。 (使用视频或音频标签)
  • 服务接收客户提交的数据(通过POSTMAN提交)
  • 服务将数据广播到其每个注册的客户端。

这是我实施的内容:

(适用Index.cshtml)

<div>
    <video  width="480" 
            height="320" 
            controls="controls" 
            autoplay="autoplay">
        <source     src="/api/video/initiate"
                    type="video/mp4">
        </source>
    </video>
</div>

StreamingService

public class StreamingService: IStreamingService
{
    public IList<Stream> Connections {get;set;}

    public StreamingService()
    {
        Connections = new List<Stream>();
    }

    public byte[] AnalyzeStream(Stream stream)
    {
        long originalPosititon = 0;
        if (stream.CanSeek)
        {
            originalPosititon = stream.Position;
            stream.Position = 0;
        }

        try
        {
            var readBuffer = new byte[4096];
            int bytesReader;

            while ((byteRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
            {
                totalBytesRead += byteRead;

                if (totalBytesRead == readBuffer.Length)
                {
                    var nextByte = stream.ReadByte();
                    if (nextByte != -1)
                    {
                        var temp = new byte[readBuffer * 2];
                        Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                        Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                        readBuffer = temp;
                        totalBytesRead++;
                    }
                }
            }

            var buffer = readBuffer;
            if (readBuffer.Length != totalBytesRead)
            {
                buffer = new byte[totalBytesRead];
                Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
            }

            return buffer;
        }
        finally
        {
            if (stream.CanSeek)
                stream.Position = originalPosititon;
        }
    }
}

的视频控制器

public class VideoController: Controller
{
    private readonly IStreamingService _streamingService;

    private readonly IHostingEnvironment _hostingEnvironment;

    public VideoController(IStreamingService streamingService, IHostingEnvironment hostingEnvironment)
    {
        _streamingService = streamingService;
        _hostingEnvironment = hostingEnvironment;
    }

    [HttpGet("initiate")]
    public IActionResult Initiate()
    {
        _streamingService.Connections.Add(Response.Body);
    }

    [HttpPost("broadcast")]
    public async Task<IActionResult> Broadcast()
    {
        // Retrieve data submitted from POSTMAN.
        var data = _streamingService.AnalyzeStream(Request.Body);

        foreach (var stream in _streamingService.Connections)
        {
            try
            {
                await stream.WriteAsync(data, 0, data.Length);
            }
            catch (Exception exception)
            {
                stream.Dispose();
                _streamingService.Connections.Remove(stream);
            }
        }
    }
}

当我从POSTMAN通过api / video / broadcast发送数据时。对于循环运行,我得到一个例外,说流已被处理。

我的问题是:

  • 如何让流保持活动状态?

(在api / video / initiate中创建的流保持活动状态,当客户端调用api / video / broadcast时,所有启动的流将更新其日期而不进行处理)

谢谢,

1 个答案:

答案 0 :(得分:0)

是否可以将流保存在缓存中?

您可以阅读更多相关信息here。最简单的方法是将缓存服务添加到依赖注入容器,并通过构造函数注入在VideoController中请求IMemoryCache的具体实现(正如您使用IStreamingService和IHostingEnvironment完成的那样)。

只需将流添加到缓存中,并在下次访问api / video / broadcast时使用缓存的流。

请注意,如果您使用的是webfarm或托管在云中,建议使用像Redis Cache这样的Distributed Cache,否则您的缓存可能会意外消失。我使用Azure Redis Cache例如,效果很好!