Stream.WriteAsync 抛出远程主机关闭连接异常

Posted

技术标签:

【中文标题】Stream.WriteAsync 抛出远程主机关闭连接异常【英文标题】:Stream.WriteAsync throws The remote host closed the connection exception 【发布时间】:2015-07-27 03:24:54 【问题描述】:

我有一个 asp.net webforms 应用程序并从数据库中检索以varbinary 格式保存的视频并将其显示为 html5 视频标签。

在谷歌上搜索后,我找到了一种我应该使用ASP.Net WebApi 异步播放它的方法,它工作正常

第一个问题

当视频第一次播放并且用户点击播放按钮重新播放视频时,The remote host closed the connection. The error code is 0x800704CD 异常在await outputStream.WriteAsync(buffer, 0, bytesRead); 行抛出。

第二个问题

当用户点击搜索栏时,视频从第一个开始播放。

注意

Internet Explorer 11 播放视频没有任何问题,但 firefox 和 chrome 都有这两个问题。

我该如何解决这个问题?

这是我的代码:

public static class WebApiConfig

    public static void Register(HttpConfiguration config)
    
        config.EnableCors();

        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "VideoApi",
            routeTemplate: "api/controller/id",
            defaults: new  id = RouteParameter.Optional 
        );
    


public class VideoController : ApiController

    public IVideoRepository videoRepository;

    public HttpResponseMessage Get(long id)
    
        try
        
            videoRepository = new VideoRepository();
            Video video = videoRepository.load(id);

            if (video != null)
            
                var videoStream = new VideoStream(video.fileContent);
                string ext = video.extension;

                var response = Request.CreateResponse();

                response.Content = new PushStreamContent((Action<Stream, HttpContent, TransportContext>)videoStream.WriteToStream, new MediaTypeHeaderValue("video/" + ext));

                response.Content.Headers.Add("Content-Disposition", "attachment;filename=" + video.fullName.Replace(" ", ""));
                response.Content.Headers.Add("Content-Length", videoStream.FileLength.ToString());

                return response;
            
            else
            
                return Request.CreateResponse(HttpStatusCode.NotFound);
            
        
        catch (Exception e)
        
            return Request.CreateErrorResponse(HttpStatusCode.ServiceUnavailable, e);
        
    


public class VideoStream

    private readonly byte[] _fileContent;
    private long _contentLength;

    public long FileLength
    
        get  return _contentLength; 
    

    public VideoStream(byte[] content)
    
        _contentLength = content.Length;
        _fileContent = content;
    

    public async void WriteToStream(Stream outputStream, HttpContent content, TransportContext context)
    
        try
        
            var buffer = new byte[65536];

            MemoryStream memoryStream = new MemoryStream();
            memoryStream.Write(_fileContent, 0, _fileContent.Length);
            memoryStream.Position = 0;
            using (memoryStream)
            
                var length = (int)memoryStream.Length;
                var bytesRead = 1;

                while (length > 0 && bytesRead > 0)
                
                    bytesRead = memoryStream.Read(buffer, 0, Math.Min(length, buffer.Length));
                    await outputStream.WriteAsync(buffer, 0, bytesRead);
                    length -= bytesRead;
                
            
        
        catch (Exception e)
        
            throw e;
        
        finally
        
            outputStream.Close();
        
    

更新

这种方式不能正常工作后,我不得不使用this way,但是新方式有seekbar问题,当用户点击seek bar来寻找时间时,它在Chrome和FireFox中不起作用。

【问题讨论】:

【参考方案1】:

ASP.NET 不太擅长视频流。第三方视频流解决方案是最佳选择。

有一些视频流服务器(如Wowza),但它们需要安装并且您必须购买许可证。

云流媒体服务是另一种选择。我个人更喜欢AWS Cloudfront。他们建议在各种全球分布的内容交付区域进行分发。它的成本非常便宜,而且您可以确定它可以承受任何流量(即使您的所有用户会同时观看同一个视频)。

【讨论】:

【参考方案2】:

您现在可能已经得到了答案。但这可能对其他人有所帮助- 我最好的选择是从响应标头中删除 Content-lengthContent-Length 告诉调用者它需要在响应中接收这个固定长度。 当您单击播放按钮时,未收到完整的视频流(即未收到整个 Content-Length。)因此出现错误。

另一种方法是使用response.Headers.TransferEncodingChunked = true,它告诉调用者它将接收到块的响应。这里唯一的问题是即使流不存在,您也会获得 200OK。

【讨论】:

以上是关于Stream.WriteAsync 抛出远程主机关闭连接异常的主要内容,如果未能解决你的问题,请参考以下文章

无法将数据写入传输连接:现有连接被远程主机强行关闭

jstatd--收集远程主机信息

[SCOI2008]奖励关

bzoj1076 奖励关

[SCOI2008] 奖励关

[SCOI2008]奖励关