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内存消耗和时间消耗问题。

测试看看吧。

时间: 2024-11-06 07:42:28

C# 利用socekt做到http监听,怎么样才能做到高性能的相关文章

android菜鸟学习笔记23----ContentProvider(三)利用内置ContentProvider监听短信及查看联系人

要使用一个ContentProvider,必须要知道的是它所能匹配的Uri及其数据存储的表的结构. 首先想办法找到访问短信及联系人数据的ContentProvider能接受的Uri: 到github上找对应ContentProvider的源码:https://github.com/android 有好多个,哪一个才是短信数据的ContentProvider呢? 在filters输入框:输入telephony. 现在只有一个了,打开: 装有git的话,可以选择clone到本地,没有的话,就选择下载

利用Node的chokidar 监听文件改变的文件。

最近维护一个项目.每次改完东西,都要上传到服务器.然后有时候就忘记一些东西,于是就想有没有可以方法能监听文件的改变.然后我再利用程序把更改的文件一键上传到服务器. 于是就找到了nodejs 的chokidar模块. 然后利用redis的set集合.因为我们频繁更改.如果用普通的字符 会增加比较.set是一个集合,里面的元素都是不重复的.正好可以利用这个特性.帮我们记录更改的记录文件.删除的时候,然后删掉set中的文件.目前只做了增加或修改的文件提交,如果本地删除的 不会同步到服务器. 监听本地文

【Android】利用Activity生命周期监听应用前后台切换

~转载请注明:http://blog.csdn.net/u013015161/article/details/46762991 实现介绍 在Android应用开发中,我们有时候需要监听到应用前后台的切换.这里提供一种思路,该思路并非原创,而是一种比较通用的办法,这里做一下介绍,附带实际过程中遇到的问题的解决. 具体实现思路是通过重写Activity的onResume方法和onStop方法实现,即在onStop里判断应用是否切换到后台,在onResume里判断是否切换到前台. 先回顾一下Activ

利用Maxwell组件实时监听Mysql的binlog日志

一:在linux环境下安装部署好mysql 开启binlog Vim  /etc/my.cnf mysql的binlog格式有3种,为了把binlog解析成json数据格式,要设置binlog的格式为row(binlog有三种格式:Statement.Row以及Mixed) 3重启msyql服务 service mysqld restart 查看是否已经开启binlog 查看是否已经开启binlog 是否改为row模式 /var/lib/mysql下看到生成了相应的binlog监听日志文件,如图

利用原生JS实时监听input框输入值

传送门https://www.cnblogs.com/lantinggumo/p/7636715.html 传送门https://www.cnblogs.com/nailc/p/8572226.html 原文地址:https://www.cnblogs.com/wzh1997/p/11135589.html

高大上的“网络监听”,其实你也能做!

出来工作一年了,回忆大学那时,我所在专业里有一位大神级人物,他每天都和我们聊一下很“美丽”的事物.他最经常喜欢所得一句话,“一切事物都可以用01表示出来”.那时的他,很喜欢分享,很喜欢去研究一些高大上的问题,数学是他的强项.那时,我们桂林高校的五子棋大赛,他拿了冠军,证明了自己,并不是一个只会说不会做的人.其实我对他还是很有好感的,不过由于各种原因吧,我们交往并不算太深.还记得的那些夜晚,学习和生活上遇到很多困惑,经常很他一起聊到11点半,讨论各种奇怪的事情.从那开始,我就渐渐地更喜欢写程序啦.

转:网络监听原理

网络监听是指利用计算机的网络接口截获目的地为第三方计算机的数据报文的一种技术.利用这种技术可以监听网络的当前流量状况:网络程序的运行以及非法窃取网络中传输的机密信息. 在共享式以太网中,所有的通讯都是广播的,也就是说通常在同一网段的所有网络接口都可以访问在物理媒体上传输的所有数据,使用ARP和RARP协议进行相互转换.在正常的情况下,一个网络接口应该只响应两种数据帧:与自己硬件地址相匹配的数据帧和发向所有机器的广播数据帧.在一个实际的系统中,数据的收发由网卡来完成.每个以太网卡拥有一个全球难一的

Android短信监听(三)——利用Loader实现短信监听

MainActivity如下: package cc.c; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.app.LoaderManager.LoaderCallbacks; import android.content.Context; import android.content.Loader; import android.database.Curs

Android短信监听(二)——利用ContentObserver实现短信监听

MainActivity如下: package cc.testsmslistener; import cc.testsmslistener.SMSContentObserver.MessageListener; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.widget.TextView; import android.app.Activity; /** *