HTTPListener类似乎在新连接时切断旧连接,这是正确的吗?

时间:2014-11-04 16:15:23

标签: c# .net http windows-media-player httplistener

我有一个充当文件主机的类,实质上你用一个端口号启动这个类并且它托管一个文件(在真实世界中实际上是包含许多部分的更大文件的主机部分 - 但是我&# 39;已经考虑到试图找到一些问题的底部)。当我托管一个小文件时,它很好并且所有工作都按预期工作,当我托管较大的文件时,我会得到一些不寻常的行为 - 特别是当我使用Windows媒体播放器向听众打开网址时。似乎Windows媒体播放器发送get请求以获取所有内容,然后是第二个请求开始收集块 - 但这些总是会导致异常"指定的网络无法再找到"。幸运的是,原始连接仍然打开,文件在媒体播放器中运行 - 但是如果我然后尝试将滑块移动到文件中的特定点,它会触发另一个错误输出的请求 - 我已经设法得到它以便窗口媒体根本不会让你移动滑块 - 但这对我们来说并不起作用。我尝试过在IIS中托管的相同文件,看起来很好,并且嗅探了数据包和匹配(至少在httplistener死之前)......我错过了什么。

以下是我使用的代码:

using SWAT.Apps.WebinarRecordingsViewer.Interfaces;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace SWAT.Apps.WebinarRecordingsViewer.Implementation.Common
{
 public class FileHost : IFileHost
{

    private long Port { get; set; }
    private string MimeType { get; set; }
    private PointerRecord PointerRecord { get; set; }
    public string FileName { get; set; }
    public string ResultingFilename { get; set; }

    public virtual string Url
    {
        get
        {
            return "http://localhost:" + this.Port + "/";
        }
    }

    public Guid Guid { get; set; }

    public FileHost(string filename, PointerRecord pointerRecord, string mimeType, long port, string resultingFilename, string realurl)
    {
        this.Port = port;
        this.MimeType = mimeType;
        this.FileName = filename;
        this.PointerRecord = pointerRecord;
        this.ResultingFilename = resultingFilename;
        this.RealUrl = realurl;
        this.Guid = Guid.NewGuid();
    }


    public void Dispose()
    {
        this.Stop();
    }


    private bool Stopped { get; set; }
    private bool Stopping { get; set; }

    public void Stop()
    {
        if (!Stopped)
        {
            Stopping = true;
            if (this.listener!=null)
            {
                this.listener.Abort(); 

            }

        }
        this.listener.Close();


    }
    public HttpListener listener { get; set; }


    public void Start()
    {
        Stopped = false;
        Stopping = false;

        this.listener = new HttpListener();
        this.listener.Prefixes.Add(string.Format("http://localhost:{0}/", this.Port));
        this.listener.Start();
        IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), this.listener);
       }



    public void ListenerCallback(IAsyncResult result)
    {
        if (this.listener == null)
            return;
        HttpListenerContext context = this.listener.EndGetContext(result);

        // Call EndGetContext to complete the asynchronous operation.
        if (!Stopping)
        {
            this.listener.BeginGetContext(new AsyncCallback(ListenerCallback), this.listener);
             this.WriteFile(context.Response, context.Request);

        }
        if (Stopping)
        {
            Stopped = true;
            Stopping = false;

        }

    }

    public string RealUrl { get; set; }

    private void WriteFile(HttpListenerResponse response, HttpListenerRequest request)
    {
         using (FileStream fs = File.Open(/*this.FileName*/"f:\\work\\download.wmv",FileMode.Open, FileAccess.Read, FileShare.Read))
        {
              response.KeepAlive = true;
            response.SendChunked = true;
            bool doingRange = false;
      //      response.AddHeader("Last-Modified", "Sun, 14 Nov 2010 21:15:21 GMT");
         //   response.ProtocolVersion = new Version("1.1");
     //       response.AddHeader("Cache-Control", "max-age=86400");
    //        response.AddHeader("ETag", string.Format("\"{0}\"", this.Guid.ToString()));
            response.AddHeader("Accept-Ranges", "bytes");
            response.ContentType = this.MimeType;
             long start = 0;
             long length = fs.Length;//this.PointerRecord.Length;
            Int64 endByte = length-1;
            if (request.Headers["range"] != null)
            {
                doingRange = true;
                start = long.Parse(request.Headers["range"].Split('=')[1].Split('-')[0].Trim()) ;
                if ((request.Headers["range"].Split('=')[1].Split('-').Length > 1))
                {
                    Int64 endread = 0;
                    Int64.TryParse(request.Headers["range"].Split('=')[1].Split('-')[1].Trim(), out endread);
                    if (endread > 0)
                    {
                        endByte = endread;
                    }

                }
                if ((endByte + 1) > this.PointerRecord.Length)
                {
                    endByte = this.PointerRecord.Length - 1;
                }

                length = (endByte - start) + 1;
                response.AddHeader("Content-Range", "bytes=" + start.ToString() + "-" + endByte.ToString() + "/" + fs.Length.ToString());
                response.ContentLength64 = length;

            }
            else
            {
                response.ContentLength64 = fs.Length;


            }

            byte[] buffer = new byte[1024 * 1024 ];

            fs.Seek(start, SeekOrigin.Begin);

            long read =0;
            long runningTotal = 0;
            try
            {
                var stream = response.OutputStream;
                while ((length > 0) && ((read = fs.Read(buffer, 0, buffer.Length)) > 0))
                {
                    runningTotal += read;
                    // if the read overshoots the requested read length
                    if (runningTotal > length)
                    {
                        read = read - (runningTotal - length);
                    }
                    stream.Write(buffer, 0, Convert.ToInt32(read));
                    stream.Flush();
                    if (runningTotal >= length)
                    {
                        break;
                    }



                }
                stream.Close();
                response.StatusCode = doingRange ? (int)HttpStatusCode.PartialContent : (int)HttpStatusCode.OK;
                response.StatusDescription = (doingRange ? HttpStatusCode.PartialContent : HttpStatusCode.OK).ToString();

            }
            catch (Exception ex)
            {
                var test = ex.Message;


            }
            finally
            {
                fs.Close();
                fs.Dispose();
            }


        }
    }




    public event EventHandler<FileHostEventArgs> Error;

    public void OnError(FileDownloadEventArgs e)
    {
        throw new NotImplementedException();
    }
}
}

我不相信这是媒体播放器是否行为不端,或者它是否是服务器代码中的某些内容......任何帮助/建议都会很棒..

1 个答案:

答案 0 :(得分:0)

原来媒体播放器是超级挑剔的,而IE只是让它走了:我做了一个错字

 response.AddHeader("Content-Range", "bytes=" + start.ToString() + "-" + endByte.ToString() + "/" + fs.Length.ToString());

应该是:

response.AddHeader("Content-Range", "bytes " + start.ToString() + "-" + endByte.ToString() + "/" + fs.Length.ToString());