zoukankan      html  css  js  c++  java
  • C# 利用socekt做到http监听,怎么样才能做到高性能

    c#原始提供了http的监听的类HttpListener,实现了简单的http。文章地址《C# 控制台或者winform程序开启http的监听状态》

    但是经过我测试,这个HttpListener提供的真的就只是简单的http监听功能,无法实现高并发处理。

    不知道是我处理问题还是其他什么原因,无法实现,当上一个http请求连接尚未关闭的情况下,即便是把请求放到另外一个线程执行,都要等到处理结束,close了才能接受和处理下一次的连接请求。

    也许你会说HttpListener不是提供了异步监听的嘛?异步不就可以类使用多线程实现嘛。但是经过我测试,确实没有得到我想要的实际效果。

    所以另辟蹊径。http其实质就是socket的tcp封装实现的功能,单次请求,处理,关闭的socket功能。

    所以这里找到了可以使用最原始的socket的来提供http监听,处理数据,关闭状态。

    好了直接上代码,,一下代码部分来至于博客园,园友帖子提供,时间久远亦不知道是哪位仁兄的帖子,见谅。

      1   internal class HttpServer
      2     {
      3         private IPEndPoint _IP;
      4         private TcpListener _Listeners;
      5         private volatile bool IsInit = false;
      6         HashSet<string> Names;
      7 
      8         /// <summary>
      9         /// 初始化服务器
     10         /// </summary>
     11         public HttpServer(string ip, int port, HashSet<string> names)
     12         {
     13             IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(ip), port);
     14             this._IP = localEP;
     15             Names = names;
     16             if (Names == null)
     17             {
     18                 Names = new HashSet<string>();
     19             }
     20             try
     21             {
     22                 foreach (var item in names)
     23                 {
     24                     Console.WriteLine(string.Format(System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff:") + "Start Listen Http Socket -> {0}:{1}{2} ", ip, port, item));
     25                 }
     26                 this._Listeners = new TcpListener(IPAddress.Parse(ip), port);
     27                 this._Listeners.Start(5000);
     28                 IsInit = true;
     29                 this.AcceptAsync();
     30             }
     31             catch (Exception ex)
     32             {
     33                 Console.WriteLine(ex);
     34                 this.Dispose();
     35             }
     36         }
     37 
     38         private void AcceptAsync()
     39         {
     40             try
     41             {
     42                 this._Listeners.BeginAcceptTcpClient(new AsyncCallback(AcceptAsync_Async), null);
     43             }
     44             catch (Exception) { }
     45         }
     46 
     47         private void AcceptAsync_Async(IAsyncResult iar)
     48         {
     49             this.AcceptAsync();
     50             try
     51             {
     52                 TcpClient client = this._Listeners.EndAcceptTcpClient(iar);
     53                 var socket = new HttpClient(client);
     54                 Console.WriteLine(System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff:") + "Create Http Socket Remote Socket LocalEndPoint:" + client.Client.LocalEndPoint + " RemoteEndPoint:" + client.Client.RemoteEndPoint.ToString());
     55                 foreach (var item in Names)
     56                 {
     57                     if (socket.http_url.StartsWith(item))
     58                     {
     59                         try
     60                         {
     61                             socket.process();
     62                             return;
     63                         }
     64                         catch { break; }
     65                     }
     66                 }
     67                 socket.WriteFailure();
     68                 socket.Close();
     69             }
     70             catch (Exception) { }
     71         }
     72 
     73         /// <summary>
     74         /// 释放资源
     75         /// </summary>
     76         public void Dispose()
     77         {
     78             if (IsInit)
     79             {
     80                 IsInit = false;
     81                 this.Dispose(true);
     82                 GC.SuppressFinalize(this);
     83             }
     84         }
     85 
     86         /// <summary>
     87         /// 释放所占用的资源
     88         /// </summary>
     89         /// <param name="flag1"></param>
     90         protected virtual void Dispose([MarshalAs(UnmanagedType.U1)] bool flag1)
     91         {
     92             if (flag1)
     93             {
     94                 if (_Listeners != null)
     95                 {
     96                     try
     97                     {
     98                         Console.WriteLine(string.Format("Stop Http Listener -> {0}:{1} ", this.IP.Address.ToString(), this.IP.Port));
     99                         _Listeners.Stop();
    100                         _Listeners = null;
    101                     }
    102                     catch { }
    103                 }
    104             }
    105         }
    106 
    107         /// <summary>
    108         /// 获取绑定终结点
    109         /// </summary>
    110         public IPEndPoint IP { get { return this._IP; } }
    111     }

    这个是实现socket监听状态

      1  public class HttpClient
      2     {
      3         private static int MAX_POST_SIZE = 10 * 1024 * 1024; // 10MB
      4         private const int BUF_SIZE = 4096;
      5         private Stream inputStream;
      6         public StreamWriter OutputStream;
      7         public String http_method;
      8         public String http_url;
      9         public String http_protocol_versionstring;
     10         public Hashtable httpHeaders = new Hashtable();
     11         internal TcpClient _Socket;
     12 
     13         /// <summary>
     14         /// 这个是服务器收到有效链接初始化
     15         /// </summary>
     16         internal HttpClient(TcpClient client)
     17         {
     18             this._Socket = client;
     19             inputStream = new BufferedStream(_Socket.GetStream());
     20             OutputStream = new StreamWriter(new BufferedStream(_Socket.GetStream()), UTF8Encoding.Default);
     21             ParseRequest();
     22         }
     23 
     24         internal void process()
     25         {
     26             try
     27             {
     28                 if (http_method.Equals("GET"))
     29                 {
     30                     Program.Pool.ActiveHttp(this, GetRequestExec());
     31                 }
     32                 else if (http_method.Equals("POST"))
     33                 {
     34                     Program.Pool.ActiveHttp(this, PostRequestExec());
     35                 }
     36             }
     37             catch (Exception e)
     38             {
     39                 Console.WriteLine("Exception: " + e.ToString());
     40                 WriteFailure();
     41             }
     42         }
     43 
     44         public void Close()
     45         {
     46             OutputStream.Flush();
     47             inputStream.Dispose();
     48             inputStream = null;
     49             OutputStream.Dispose();
     50             OutputStream = null; // bs = null;            
     51             this._Socket.Close();
     52         }
     53 
     54         #region 读取流的一行 private string ReadLine()
     55         /// <summary>
     56         /// 读取流的一行
     57         /// </summary>
     58         /// <returns></returns>
     59         private string ReadLine()
     60         {
     61             int next_char;
     62             string data = "";
     63             while (true)
     64             {
     65                 next_char = this.inputStream.ReadByte();
     66                 if (next_char == '\n') { break; }
     67                 if (next_char == '\r') { continue; }
     68                 if (next_char == -1) { Thread.Sleep(1); continue; };
     69                 data += Convert.ToChar(next_char);
     70             }
     71             return data;
     72         }
     73         #endregion
     74 
     75         #region 转化出 Request private void ParseRequest()
     76         /// <summary>
     77         /// 转化出 Request
     78         /// </summary>
     79         private void ParseRequest()
     80         {
     81             String request = ReadLine();
     82             if (request != null)
     83             {
     84                 string[] tokens = request.Split(' ');
     85                 if (tokens.Length != 3)
     86                 {
     87                     throw new Exception("invalid http request line");
     88                 }
     89                 http_method = tokens[0].ToUpper();
     90                 http_url = tokens[1];
     91                 http_protocol_versionstring = tokens[2];
     92             }
     93             String line;
     94             while ((line = ReadLine()) != null)
     95             {
     96                 if (line.Equals(""))
     97                 {
     98                     break;
     99                 }
    100                 int separator = line.IndexOf(':');
    101                 if (separator == -1)
    102                 {
    103                     throw new Exception("invalid http header line: " + line);
    104                 }
    105                 String name = line.Substring(0, separator);
    106                 int pos = separator + 1;
    107                 while ((pos < line.Length) && (line[pos] == ' '))
    108                 {
    109                     pos++;//过滤键值对的空格
    110                 }
    111                 string value = line.Substring(pos, line.Length - pos);
    112                 httpHeaders[name] = value;
    113             }
    114         }
    115         #endregion
    116 
    117         #region 读取Get数据 private Dictionary<string, string> GetRequestExec()
    118         /// <summary>
    119         /// 读取Get数据
    120         /// </summary>
    121         /// <returns></returns>
    122         private Dictionary<string, string> GetRequestExec()
    123         {
    124             Dictionary<string, string> datas = new Dictionary<string, string>();
    125             int index = http_url.IndexOf("?", 0);
    126             if (index >= 0)
    127             {
    128                 string data = http_url.Substring(index + 1);
    129                 datas = getData(data);
    130             }
    131             WriteSuccess();
    132             return datas;
    133         }
    134         #endregion
    135 
    136         #region 读取提交的数据 private void handlePOSTRequest()
    137         /// <summary>
    138         /// 读取提交的数据
    139         /// </summary>
    140         private Dictionary<string, string> PostRequestExec()
    141         {
    142             int content_len = 0;
    143             MemoryStream ms = new MemoryStream();
    144             if (this.httpHeaders.ContainsKey("Content-Length"))
    145             {
    146                 //内容的长度
    147                 content_len = Convert.ToInt32(this.httpHeaders["Content-Length"]);
    148                 if (content_len > MAX_POST_SIZE) { throw new Exception(String.Format("POST Content-Length({0}) 对于这个简单的服务器太大", content_len)); }
    149                 byte[] buf = new byte[BUF_SIZE];
    150                 int to_read = content_len;
    151                 while (to_read > 0)
    152                 {
    153                     int numread = this.inputStream.Read(buf, 0, Math.Min(BUF_SIZE, to_read));
    154                     if (numread == 0)
    155                     {
    156                         if (to_read == 0) { break; }
    157                         else { throw new Exception("client disconnected during post"); }
    158                     }
    159                     to_read -= numread;
    160                     ms.Write(buf, 0, numread);
    161                 }
    162                 ms.Seek(0, SeekOrigin.Begin);
    163             }
    164             WriteSuccess();
    165             StreamReader inputData = new StreamReader(ms);
    166             string data = inputData.ReadToEnd();
    167             return getData(data);
    168         }
    169         #endregion
    170 
    171         #region 输出状态
    172         /// <summary>
    173         /// 输出200状态
    174         /// </summary>
    175         public void WriteSuccess()
    176         {
    177             OutputStream.WriteLine("HTTP/1.0 200 OK");
    178             OutputStream.WriteLine("Content-Type: text/html");
    179             OutputStream.WriteLine("Connection: close");
    180             OutputStream.WriteLine("");
    181         }
    182 
    183         /// <summary>
    184         /// 输出状态404
    185         /// </summary>
    186         public void WriteFailure()
    187         {
    188             OutputStream.WriteLine("HTTP/1.0 404 File not found");
    189             OutputStream.WriteLine("Content-Type: text/html");
    190             OutputStream.WriteLine("Connection: close");
    191             OutputStream.WriteLine("");
    192         }
    193         #endregion
    194 
    195         /// <summary>
    196         /// 分析http提交数据分割
    197         /// </summary>
    198         /// <param name="rawData"></param>
    199         /// <returns></returns>
    200         private static Dictionary<string, string> getData(string rawData)
    201         {
    202             var rets = new Dictionary<string, string>();
    203             string[] rawParams = rawData.Split('&');
    204             foreach (string param in rawParams)
    205             {
    206                 string[] kvPair = param.Split('=');
    207                 string key = kvPair[0];
    208                 string value = HttpUtility.UrlDecode(kvPair[1]);
    209                 rets[key] = value;
    210             }
    211             return rets;
    212         }
    213     }

    实现了对http数据请求处理

    1 public interface ISocketPool
    2     {
    3         /// <summary>
    4         /// 
    5         /// </summary>
    6         /// <param name="client"></param>
    7         void ActiveHttp(Fly.Network.SocketPool.Http.HttpClient client, Dictionary<string, string> parms);
    8     }
     1 public class Program
     2     {
     3         public static MessagePool Pool = new MessagePool();
     4         static void Main(string[] args)
     5         {
     6             HttpServer https = new HttpServer("127.0.0.1", 80, new HashSet<string>() {"/test/","/flie/" });
     7             Console.ReadLine();
     8         }
     9     }
    10     class MessagePool : ISocketPool
    11     {
    12         public void ActiveHttp(HttpClient client, Dictionary<string, string> parms)
    13         {
    14             Thread.Sleep(new Random().Next(0, 3000));
    15             foreach (var item in parms)
    16             {
    17                 Console.WriteLine(DateTime.Now.NowString() + "item.Key:" + item.Key + "; item.Value:" + item.Value);
    18             }
    19             string strHtml = @"
    20 <html><head></head>
    21 <body>
    22 <div>&nbsp;</div>
    23 <div>&nbsp;</div>
    24 <div>&nbsp;</div>
    25 <div>&nbsp;</div>
    26 <div>&nbsp;</div>
    27 {0}
    28 </body>
    29 </html>
    30 ";
    31             client.OutputStream.WriteLine(string.Format(strHtml, DateTime.Now.NowString() + "xxxxxxxxxxx"));
    32             client.Close();
    33         }
    34     }

    程序启动过后,看到输出

    2015-04-13 16:23:21:059:Start Listen Http Socket -> 127.0.0.1:80/test/
    2015-04-13 16:23:21:069:Start Listen Http Socket -> 127.0.0.1:80/flie/

    接下来我们在浏览器输入 127.0.0.1/test/

    正常收到请求,输出程序

    127.0.0.1/test/

    这里test1这个并不是我们监听饿目录,根本不会处理,

    接下来我们再看看这个效果 get提交的参数 127.0.0.1/test/?bb=test

    输出了get提交过来的参数信息。可能你会奇怪,为什么一次请求会收到两次连接请求。这里我查看过了其中一次请求是浏览器自带的请求页面标签的icon连接请求,

    如果你拷贝了程序,你现在可以实现跑来程序,然后输入网址,按着F5不放,看看服务器的承受能力,当然这里忽律了逻辑方面对cpu内存消耗和时间消耗问题。

    测试看看吧。

    跪求保留标示符
    /**
     * @author: Troy.Chen(失足程序员, 15388152619)
     * @version: 2021-07-20 10:55
     **/
    
    C#版本代码 vs2010及以上工具可以
    
    java 开发工具是netbeans 和 idea 版本,只有项目导入如果出现异常,请根据自己的工具调整
    
    
    提供免费仓储。
    最新的代码地址:↓↓↓
    https://gitee.com/wuxindao
    
    觉得我还可以,打赏一下吧,你的肯定是我努力的最大动力
        
    
  • 相关阅读:
    WPF(ContentControl和ItemsControl)
    WPF(x:Key 使用)
    WPF(Binding集合对象数据源)
    WPF(x:Type的使用)
    WPF(初识DataTemplate)
    Asp.net 全局错误处理
    给年轻程序员的建议(转自csdn)
    在.net中未能用trycatch捕获到的异常处理(转载)
    c#语音读取文字
    IIS 7.0 和 IIS 7.5 中的 HTTP 状态代码
  • 原文地址:https://www.cnblogs.com/shizuchengxuyuan/p/4422544.html
Copyright © 2011-2022 走看看