利用Httplistener实现的HttpServer类

9 篇文章 0 订阅
4 篇文章 0 订阅

毕设中有一个文件传输的功能模块,所以用Httplistener类写了一个HttpServer类作为一个简单的web服务器,这样客户端下载文件就很简单了。

using System;
using System.Net;
using System.Text;
using System.Threading;
using System.IO;
using System.Security.Principal;
using System.Net.NetworkInformation;
using System.Net.Sockets;

namespace Test
{
    class HttpServer
    {
        string port;
        string homeDir;
        HttpListener listener;
        Thread listenThread;

        public HttpServer(string port, string homeDir)
        {
            this.port = port;
            this.homeDir = homeDir;
        }
        /// <summary>
        /// 设置监听端口,重启服务生效
        /// </summary>
        //public string Port
        //{
        //    get { return this.port; }
        //    set
        //    {
        //        int p;
        //        if (string.IsNullOrEmpty(value) || !int.TryParse(value, out p))
        //        {
        //            throw new Exception("给http监听器赋值的端口号无效!");
        //        }
        //        this.port = value;
        //    }
        //}
        /// <summary>
        /// http服务根目录
        /// </summary>
        public string HomeDir
        {
            get { return this.homeDir; }
            set
            {
                if (!File.Exists(value))
                    throw new Exception("http服务器设置的根目录不存在!");
                this.homeDir = value;
            }
        }
        /// <summary>
        /// 服务器是否在运行
        /// </summary>
        public bool IsRunning
        {
            get { return (listener == null) ? false : listener.IsListening; }
        }
        /// <summary>
        /// 启动服务
        /// </summary>
        public void Start()
        {
            if (listener != null)
                return;
            listener = new HttpListener();
            listener.Prefixes.Add("http://+:" + this.port + "/");
            listener.Start();
            listenThread = new Thread(AcceptClient);
            listenThread.Name = "httpserver";
            listenThread.Start();
        }
        /// <summary>
        /// 停止服务
        /// </summary>
        public void Stop()
        {
            if (listener != null)
            {
                listener.Stop();
            }
        }
        /// <summary>
        /// /接受客户端请求
        /// </summary>
        void AcceptClient()
        {
            while (listener.IsListening)
            {
                try
                {
                    HttpListenerContext context = listener.GetContext();
                    new Thread(HandleRequest).Start(context);
                }
                catch 
                {
                }
            }
           
        }
        //处理客户端请求
        void HandleRequest(object ctx)
        {
            HttpListenerContext context = ctx as HttpListenerContext;
            HttpListenerRequest request = context.Request;
            HttpListenerResponse response = context.Response;

            if (request.HttpMethod.ToUpper() != "GET")  //只允许get请求方式
            {
                response.ContentLength64 = 0;
                response.StatusCode = 404;
                response.Abort();
                return;
            }
            string uri = System.Web.HttpUtility.UrlDecode(request.RawUrl);
            uri = uri.Substring(uri.IndexOf("/") + 1);
            uri = uri.Replace("/", Path.DirectorySeparatorChar.ToString());
            uri = Path.Combine(homeDir, uri); 

            if (!File.Exists(uri))  //请求的文件不存在
            {
                response.StatusCode = 404;
                response.Close();
                return;
            }
           
            //向客户端传输请求的文件
            FileStream stream = new FileStream(uri, FileMode.Open, FileAccess.Read, FileShare.Read);
            try
            {
                response.ContentLength64 = stream.Length;
                response.ContentType = GetContentType(Path.GetExtension(uri));
                byte[] buff = new byte[4096];

                int count = 0;
                while ((count = stream.Read(buff, 0, 4096)) != 0)
                {
                     context.Response.OutputStream.Write(buff, 0, count);
                }

                response.Close();
                stream.Close();
            }
            catch
            {
                stream.Close();
            }
            //finally
            //{
            //    //response.OutputStream.Flush();
            //    Thread.Sleep(100);
            //    response.Close();
            //    stream.Close();
            //}
            /*
             * 存在问题:在cach或finally分支中调用response.Close();或response.OutputStram.Close()时有时会报异常“在写入所有字节之前不能关闭流”。
             * 可能原因:由于在try中出现异常时文件未传输完成,当传输的文件大小未达到response.ContentLength64 = stream.Length;中指定的大小而关闭response时就会报此异常,
             * 实现中当客户端断开连接时就会出现此异常。
             * 调试中发现try中发生的异常为:“指定的网络名不再可用”, 暂未找到解决此异常的办法。
             */
        }

        /// <summary>
        /// 获取文件对应MIME类型
        /// </summary>
        /// <param name="fileExtention">文件扩展名,如.jpg</param>
        /// <returns></returns>
        string GetContentType(string fileExtention)
        {
            switch (fileExtention)
            {
                case ".jpg":
                case ".jpeg":
                    return "image/jpeg";
                case ".html":
                    return "text/html";
                default:
                    return "application/octet-stream";
            }
        }
    }
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值