HttpServer.cs 5.9 KB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace SmartShelf.Common
{
    public class HttpServer
    {
        private static TcpListener serverListener;

        /// <summary>
        /// 接收请求:例:请求地址为http://localhost:80/abc.html?id=1&name=abc那么reqPath为/abc.html参数字符串为id=1&name=abc
        /// 当为POST请求时, 参数字符串是body的内容
        /// </summary>
        /// <param name="reqPath">请求地址,首页为空</param>
        /// <param name="paramStr">请求参数Map</param>
        /// <returns>返回的字符串结果</returns>
        public delegate string OnReceived(string reqPath, string paramStr);

        /// <summary>
        /// 启动一个Http服务器
        /// </summary>
        /// <param name="onReceived">接收请求的处理方法</param>
        /// <param name="port">端口号,默认为80</param>
        public static void Start(OnReceived onReceived, int port = 80)
        {
            if (serverListener == null)
            {
                Task.Factory.StartNew(delegate ()
                {
                    ProcessListener(onReceived, port);
                });
            }

        }
        /// <summary>
        /// 停止Http监听
        /// </summary>
        public static void Stop()
        {
            try
            {
                LogUtil.debug("Stop Http Listener\n");
                serverListener.Stop();
                serverListener = null;
            }
            catch { }
        }

        /// <summary>
        /// 解析HttpGet的参数到map中
        /// </summary>
        /// <param name="reqParams"></param>
        /// <returns></returns>
        public Dictionary<string, string> ResolveHttpGetParams(string reqParams)
        {
            Dictionary<string, string> reqParamMap = new Dictionary<string, string>();
            string[] paras = reqParams.Split('&');
            foreach (string item in paras)
            {
                string[] keyValue = item.Split('=');
                string key = keyValue[0];
                string value = "";
                if (keyValue.Length > 1)
                {
                    value = Uri.UnescapeDataString(keyValue[1]);
                }
                reqParamMap[key] = value;
            }
            return reqParamMap;
        }

        private static void hadle(Socket client, OnReceived onReceived)
        {
            try
            {
                string ip = (client.RemoteEndPoint as System.Net.IPEndPoint).Address.ToString();
                byte[] buffer = new byte[1024];
                int count = client.Receive(buffer);
                if (count > 0)
                {
                    string content = Encoding.UTF8.GetString(buffer, 0, count);

                    LogUtil.debug(content + "\n");
                    // 解析 content
                    string[] requestLines = content.Split('\n');
                    string[] requestInfo = requestLines[0].Split(' ') ;
                    string method = requestInfo[0];
                    string reqPath = "";
                    string reqParamStr = "";
                    if ("GET" == method.ToUpper())
                    {
                        string[] pathInfos = requestInfo[1].Split('?');
                        reqPath = pathInfos[0];
                        if (pathInfos.Length > 1)
                        {
                            reqParamStr = pathInfos[1];
                        }
                    }
                    else
                    {
                        //POST
                        reqPath = requestInfo[1];
                        //从body中取参数
                        int contentLength = 0;
                        string contentLengthStr = requestLines[3].Split(':')[1].Replace("\r", "");
                        Int32.TryParse(contentLengthStr, out contentLength);
                        if (contentLength > 0)
                        {
                            reqParamStr = content.Substring(content.Length - contentLength);
                        }
                    }
                    
                    string responseBody = onReceived?.Invoke(reqPath, reqParamStr);

                    string headStr = @"HTTP/1.0 200 OK
Content-Type: text/json
Connection: keep-alive
Content-Encoding: utf-8

";
                    string data =headStr + responseBody;
                    client.Send(Encoding.UTF8.GetBytes(data));
                }
            }
            catch { }
            finally
            {
                try
                {
                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                    client.Dispose();
                }
                catch { }
            }
        }

        private static void ProcessListener(OnReceived onReceived, int port)
        {
            //初始化端点信息
            IPAddress address = IPAddress.Any;
            IPEndPoint endPoint = new IPEndPoint(address, port);
            //初始化并启动监听器
            serverListener = new TcpListener(endPoint);
            serverListener.Start();
            LogUtil.debug("Start Http listener on " + port + "\n");
            while (true)
            {
                //挂起并接受请求
                Socket client = serverListener.AcceptSocket();
                LogUtil.debug("Receive a http request from " + client.RemoteEndPoint.ToString() + "\n");

                try
                {
                    hadle(client, onReceived);
                }
                catch (Exception ex)
                {
                    LogUtil.info(ex.Message);
                }
                finally
                {
                    //关闭TcpClient对象,回收资源
                    client.Close();
                }
            }
        }
    }
}