通过HttpListener实现简单的Http服务

基本概念

HttpListener提供一个简单的、可通过编程方式控制的 HTTP 协议侦听器。通过它可以很容易的提供一些Http服务,而无需启动IIS这类大型服务程序。
注意:该类仅在运行 Windows XP SP2 或 Windows Server 2003 操作系统的计算机上可用。
使用Http服务一般步骤如下:
1 创建一个HTTP侦听器对象并初始化
2 添加需要监听的URI 前缀
3 开始侦听来自客户端的请求
4 处理客户端的Http请求
5 关闭HTTP侦听器
其中3,4两步可以循环处理,以提供多客户多次请求的服务。
创建一个HTTP侦听器对象
创建HTTP侦听器对象只需要新建一个HttpListener对象即可。
HttpListener listener = new HttpListener();
初始化需要经过如下两步
添加需要监听的URL范围至listener.Prefixes中,可以通过如下函数实现:
listener.Prefixes.Add(prefix)    //prefix必须以'/'结尾
调用listener.Start()实现端口的绑定,并开始监听客户端的需求。
接受HTTP请求
在.net2.0中,通过HttpListenerContext对象提供对HttpListener类使用的请求和响应对象的访问。
获取HttpListenerContext的最简单方式如下:
HttpListenerContext context = listener.GetContext();
该方法将阻塞调用函数至接收到一个客户端请求为止,如果要提高响应速度,可使用异步方法listener.BeginGetContext()来实现HttpListenerContext对象的获取。
处理HTTP请求
获取HttpListenerContext后,可通过Request属性获取表示客户端请求的对象,通过Response属性取表示 HttpListener 将要发送到客户端的响应的对象。
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
这里的HttpListenerRequest对象和HttpListenerResponse对象和Asp中的Request和Response的使用方式类似,这里就不多说了,具体的使用可以参看下面的例子。
关闭HTTP侦听器
通过调用listener.Stop()函数即可关闭侦听器,并释放相关资源

异步方法listener

====== 异步方法listener ======

[csharp] view plaincopy
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using DevSDK.Net.Sockets;
  8. using System.IO;
  9. namespace ConsoleApplication1
  10. {
  11. class Program
  12. {
  13. static HttpListener sSocket = null;
  14. static void Main(string[] args)
  15. {
  16. sSocket = new HttpListener();
  17. sSocket.Prefixes.Add("http://127.0.0.1:8080/");
  18. sSocket.Start();
  19. sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);
  20. Console.Read();
  21. }
  22. static void GetContextCallBack(IAsyncResult ar)
  23. {
  24. try
  25. {
  26. sSocket = ar.AsyncState as HttpListener;
  27. HttpListenerContext context = sSocket.EndGetContext(ar);
  28. sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);
  29. Console.WriteLine(context.Request.Url.PathAndQuery);
  30. //其它处理code
  31. }
  32. catch { }
  33. }
  34. }
  35. }

非异步方法listener

====== C# 利用HttpListener监听处理Http请求 ======

[csharp] view plaincopy
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Net;
  6. using System.Net.Sockets;
  7. using System.IO;
  8. using System.Xml.Serialization;
  9. using System.Threading;
  10. using System.Web;
  11. namespace Test
  12. {
  13. class Program
  14. {
  15. static void Main(string[] args)
  16. {
  17. try
  18. {
  19. HttpListener listerner = new HttpListener();
  20. {
  21. for (; true; )
  22. {
  23. try
  24. {
  25. listerner.AuthenticationSchemes = AuthenticationSchemes.Anonymous;//指定身份验证 Anonymous匿名访问
  26. listerner.Prefixes.Add("http://192.168.1.10:1500/ApiService/");
  27. listerner.Start();
  28. }
  29. catch (Exception e)
  30. {
  31. Console.WriteLine("未能成功连接服务器.....");
  32. listerner = new HttpListener();
  33. continue;
  34. }
  35. break;
  36. }
  37. Console.WriteLine("服务器启动成功.......");
  38. int maxThreadNum, portThreadNum;
  39. //线程池
  40. int minThreadNum;
  41. ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum);
  42. ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum);
  43. Console.WriteLine("最大线程数:{0}", maxThreadNum);
  44. Console.WriteLine("最小空闲线程数:{0}", minThreadNum);
  45. Console.WriteLine("\n\n等待客户连接中。。。。");
  46. while (true)
  47. {
  48. //等待请求连接
  49. //没有请求则GetContext处于阻塞状态
  50. HttpListenerContext ctx = listerner.GetContext();
  51. ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc), ctx);
  52. }
  53. con.Close();
  54. listerner.Stop();
  55. }
  56. }
  57. catch (Exception e)
  58. {
  59. Console.WriteLine(e.Message);
  60. Console.Write("Press any key to continue . . . ");
  61. Console.ReadKey( );
  62. }
  63. }
  64. static void TaskProc(object o)
  65. {
  66. HttpListenerContext ctx = (HttpListenerContext)o;
  67. ctx.Response.StatusCode = 200;//设置返回给客服端http状态代码
  68. string type = ctx.Request.QueryString["type"];
  69. string userId = ctx.Request.QueryString["userId"];
  70. string password = ctx.Request.QueryString["password"];
  71. string filename = Path.GetFileName(ctx.Request.RawUrl);
  72. string userName = HttpUtility.ParseQueryString(filename).Get("userName");//避免中文乱码
  73. //进行处理
  74. //使用Writer输出http响应代码
  75. using (StreamWriter writer = new StreamWriter(ctx.Response.OutputStream))
  76. {
  77. writer.Write(“处理结果”);
  78. writer.Close();
  79. ctx.Response.Close();
  80. }
  81. }
  82. }
  83. }

Android客户端:

[java] view plaincopy
  1. public static void Register(final Handler handler, final Context context,
  2. final String userId, final String userName,final int groupId, final String password){
  3. new Thread(new Runnable(){
  4. public void run() {
  5. if(!CommonTools.checkNetwork(context)){
  6. Message msg = new Message();
  7. msg.what = Signal.NETWORK_ERR;
  8. handler.sendMessage(msg);
  9. return;
  10. }
  11. try {
  12. String content = "";
  13. String tmp   =   java.net.URLEncoder.encode(userName,   "utf-8");   //防止中文乱码
  14. URL url = new URL(URL+"?type=Register&userId="+userId+"&password="+password+"&groupId="+groupId+"&userName="+tmp);
  15. // HttpURLConnection
  16. HttpURLConnection httpconn = (HttpURLConnection) url.openConnection();
  17. if (httpconn.getResponseCode() == HttpURLConnection.HTTP_OK) {
  18. InputStreamReader isr = new InputStreamReader(httpconn.getInputStream(), "utf-8");
  19. int i;
  20. // read
  21. while ((i = isr.read()) != -1) {
  22. content = content + (char) i;
  23. }
  24. isr.close();
  25. }
  26. //disconnect
  27. httpconn.disconnect();
  28. } catch (Exception e) {
  29. e.printStackTrace();
  30. }
  31. }//run
  32. }).start();//thread
  33. }

注意:
1.中文乱码问题
   在客户端采用如下形式
   String tmp   =   java.net.URLEncoder.encode(userName,   "utf-8");   //防止中文乱码
   服务器端
   string filename = Path.GetFileName(ctx.Request.RawUrl);
   string userName = HttpUtility.ParseQueryString(filename).Get("userName");//避免中文乱码
   服务器端需要引入: using System.Web;
   此时可能提示找不到库,则在项目右键添加引用 找到 System.Web.dll勾选即可
2.[System.Net.HttpListenerException] = {"拒绝访问。"}问题
   如果是win7或者win8,在cmd.exe上右键,以管理员身份运行,然后执行下面的命令
   netsh http add urlacl url=http://本机IP:1500/ user=用户名(如Administrator)
3.记得关闭防火墙,或者只开放指定端口,步骤如下:
        step1、点击控制面板
  step2、选择windows防火墙,点击高级设置
  step3、在弹出的“高级安全windows防火墙”点击“入站规则”,在右侧“操作”栏点击“入站规则”下的“新建规则…”,此时会弹出一个窗口让你设置。剩下的就非常傻瓜化了。
  step4、弹出“新建入站规则向导”-规则类型-选中“端口”,点击下一步。选择规则应用的协议“TCP/UDP”如果是TCP你就选择TCP,UDP就选择UDP。再勾选“特定本地端口”在文本框输入您想开放的端口号(例如1521)。
  step5、点击下一步,到“连接符合指定条件时应该进行什么操作?”选择“允许连接”。点击下一步到“配置文件”何时应用该规则,勾选“域”、“专用”、“公用”点击下一步。
  step6、配置规则名称,随便输入你自己认为好记的规则名称即可。

非异步方法listener 自开线程处理请求

====== 非异步方法listener 自开线程处理请求 ======

[csharp] view plaincopy
  1. using System;
  2. using System.IO;
  3. using System.Net;
  4. using System.Text;
  5. using System.Threading;
  6. namespace HttpHelper
  7. {
  8. /// <summary>
  9. /// HTTP请求监听
  10. /// </summary>
  11. public class HttpListeners
  12. {
  13. private static HttpListener _httpListener;
  14. static readonly int Port = 1005;
  15. static HttpListeners()
  16. {
  17. ListenerStart();
  18. }
  19. private static bool ListenerStop()
  20. {
  21. try
  22. {
  23. if (_httpListener != null)
  24. {
  25. //LogInfo("停止监听端口:" + Port);
  26. _httpListener.Stop();
  27. }
  28. return true;
  29. }
  30. catch (Exception e)
  31. {
  32. //LogError(e.Message + e.StackTrace);
  33. return false;
  34. }
  35. }
  36. /// <summary>
  37. /// 监听端口
  38. /// </summary>
  39. private static void ListenerStart()
  40. {
  41. try
  42. {
  43. _httpListener = new HttpListener { AuthenticationSchemes = AuthenticationSchemes.Anonymous };
  44. _httpListener.Prefixes.Add(string.Format("http://+:{0}/",Port));
  45. _httpListener.Start();
  46. //LogInfo("开始监听端口:" + Port);
  47. while (true)
  48. {
  49. try
  50. {
  51. //监听客户端的连接,线程阻塞,直到有客户端连接为止
  52. var client = _httpListener.GetContext();
  53. new Thread(HandleRequest).StartAsync(client);
  54. }
  55. catch (Exception ex)
  56. {
  57. //LogError(ex.Message + ex.StackTrace);
  58. }
  59. }
  60. }
  61. catch (Exception e)
  62. {
  63. //LogError(e.Message + e.StackTrace);
  64. Environment.Exit(0);
  65. }
  66. }
  67. private static void HandleRequest(object obj)
  68. {
  69. var client = obj as HttpListenerContext;
  70. if (client == null) return;
  71. try
  72. {
  73. var coding = Encoding.UTF8;
  74. var request = client.Request;
  75. // 取得回应对象
  76. var response = client.Response;
  77. response.StatusCode = 200;
  78. response.ContentEncoding = coding;
  79. Console.WriteLine("{0} {1} HTTP/1.1", request.HttpMethod, request.RawUrl);
  80. Console.WriteLine("Accept: {0}", string.Join(",", request.AcceptTypes));
  81. Console.WriteLine("Accept-Language: {0}",
  82. string.Join(",", request.UserLanguages));
  83. Console.WriteLine("User-Agent: {0}", request.UserAgent);
  84. Console.WriteLine("Accept-Encoding: {0}", request.Headers["Accept-Encoding"]);
  85. Console.WriteLine("Connection: {0}",
  86. request.KeepAlive ? "Keep-Alive" : "close");
  87. Console.WriteLine("Host: {0}", request.UserHostName);
  88. Console.WriteLine("Pragma: {0}", request.Headers["Pragma"]);
  89. // 构造回应内容
  90. string responseString = @"<html><head><title>HttpListener Test</title></head><body><div>Hello, world.</div></body></html>";
  91. byte[] buffer = Encoding.UTF8.GetBytes(responseString);
  92. //对客户端输出相应信息.
  93. response.ContentLength64 = buffer.Length;
  94. Stream output = response.OutputStream;
  95. output.Write(buffer, 0, buffer.Length);
  96. //关闭输出流,释放相应资源
  97. output.Close();
  98. }
  99. catch (Exception e)
  100. {
  101. //LogError(e.Message + e.StackTrace);
  102. }
  103. finally
  104. {
  105. try
  106. {
  107. client.Response.Close();
  108. }
  109. catch (Exception e)
  110. {
  111. //LogError(e.Message);
  112. }
  113. }
  114. }
  115. }
  116. }

=== ThreadHelper ===

[csharp] view plaincopy
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. namespace HttpHelper
  8. {
  9. public static class ThreadHelper
  10. {
  11. /// <summary>
  12. /// 开启同步多线程
  13. /// </summary>
  14. public static void StartSync(this IEnumerable<Thread> threads, object startPara = null, Func<object, object> callback = null)
  15. {
  16. var ts = threads.ToArray();
  17. //启动线程
  18. foreach (var thread in ts)
  19. {
  20. if (!thread.IsBackground)
  21. {
  22. thread.IsBackground = true;
  23. }
  24. var times = 0;
  25. while (thread.ThreadState == (ThreadState.Background | ThreadState.Unstarted) && times < 10)
  26. {
  27. try
  28. {
  29. if (startPara == null)
  30. {
  31. thread.Start();
  32. }
  33. else
  34. {
  35. thread.Start(startPara);
  36. }
  37. }
  38. catch (Exception e)
  39. {
  40. times++;
  41. }
  42. Thread.Sleep(100);
  43. }
  44. }
  45. Thread.Sleep(2000);
  46. //等待全部结束
  47. foreach (var thread in ts)
  48. {
  49. try
  50. {
  51. thread.Join();
  52. }
  53. catch (Exception e)
  54. {
  55. }
  56. }
  57. if (callback != null)
  58. {
  59. callback(startPara);
  60. }
  61. }
  62. /// <summary>
  63. /// 开启多线程
  64. /// </summary>
  65. public static void StartAsync(this IEnumerable<Thread> threads, object startPara = null, Func<object, object> callback = null)
  66. {
  67. var ts = threads.ToArray();
  68. //启动线程
  69. foreach (var thread in ts)
  70. {
  71. if (!thread.IsBackground)
  72. {
  73. thread.IsBackground = true;
  74. }
  75. var times = 0;
  76. while (thread.ThreadState == (ThreadState.Background | ThreadState.Unstarted) && times < 10)
  77. {
  78. try
  79. {
  80. if (startPara == null)
  81. {
  82. thread.Start();
  83. }
  84. else
  85. {
  86. thread.Start(startPara);
  87. }
  88. }
  89. catch (Exception e)
  90. {
  91. times++;
  92. }
  93. Thread.Sleep(100);
  94. }
  95. }
  96. if (callback != null)
  97. {
  98. callback(startPara);
  99. }
  100. }
  101. /// <summary>
  102. /// 开启同步线程
  103. /// </summary>
  104. public static void StartSync(this Thread thread, object parameter = null)
  105. {
  106. try
  107. {
  108. if (!thread.IsBackground)
  109. {
  110. thread.IsBackground = true;
  111. }
  112. if (parameter == null)
  113. {
  114. thread.Start();
  115. }
  116. else
  117. {
  118. thread.Start(parameter);
  119. }
  120. }
  121. catch (Exception e)
  122. {
  123. }
  124. Thread.Sleep(1000);
  125. try
  126. {
  127. thread.Join();
  128. }
  129. catch (Exception e)
  130. {
  131. }
  132. }
  133. /// <summary>
  134. /// 开启带超时的同步线程
  135. /// </summary>
  136. public static void StartSyncTimeout(this Thread thread, int timeoutSeconds, object parameter = null)
  137. {
  138. try
  139. {
  140. if (!thread.IsBackground)
  141. {
  142. thread.IsBackground = true;
  143. }
  144. if (parameter == null)
  145. {
  146. thread.Start();
  147. }
  148. else
  149. {
  150. thread.Start(parameter);
  151. }
  152. thread.Join(timeoutSeconds * 1000);
  153. }
  154. catch (Exception e)
  155. {
  156. }
  157. }
  158. /// <summary>
  159. /// 开启异步线程
  160. /// </summary>
  161. public static void StartAsync(this Thread thread, object parameter = null)
  162. {
  163. try
  164. {
  165. if (!thread.IsBackground)
  166. {
  167. thread.IsBackground = true;
  168. }
  169. if (parameter == null)
  170. {
  171. thread.Start();
  172. }
  173. else
  174. {
  175. thread.Start(parameter);
  176. }
  177. }
  178. catch (Exception e)
  179. {
  180. }
  181. }
  182. }
  183. }

=== end ===

通过HttpListener实现简单的Http服务相关推荐

  1. Docker安装Apache与运行简单的web服务——httpd helloworld

    Docker运行简单的web服务--httpd helloworld目录[阅读时间:约5分钟] 一.Docker简介 二.Docker的安装与配置[CentOS环境] 三.Docker运行简单的web ...

  2. SpringCloud(第 002 篇)简单电影微服务类(消费方,而提供方为用户微服务)

    2019独角兽企业重金招聘Python工程师标准>>> SpringCloud(第 002 篇)简单电影微服务类(消费方,而提供方为用户微服务) 一.大致介绍 微服务与微服务之间通过 ...

  3. [WS]使用Axis发布简单的Web服务

    使用Axis,要发布一个Web服务非常简单,简直不能再简单了,尽管看起来过程和相关代码有些长.我这个帖子里用到了这些软件:Axis 1.1.Eclipse 2.1和Eclipse的Tomcat插件2. ...

  4. 使用Axis2创建一个简单的WebService服务

    使用过Java进行过WebService开发都会听过或者接触过Apache Axis2,Axis2框架是应用最广泛的WebService框架之一了. 这里使用Axis2来开发和部署一个最简单的WebS ...

  5. SpringCloud(第 054 篇)简单 Quartz-Cluster 微服务,采用注解配置 Quartz 分布式集群...

    2019独角兽企业重金招聘Python工程师标准>>> SpringCloud(第 054 篇)简单 Quartz-Cluster 微服务,采用注解配置 Quartz 分布式集群 一 ...

  6. .NET 搭建简单的通知服务

    搭建简单的通知服务 Intro 很多情况下,我们都会遇到一些需要进行通知报警的场景,比如说服务器资源监控报警,抢到火车票后通知用户进行付款. 原来主要是用的钉钉群里的机器人来做的通知,周末看到原来做 ...

  7. 构建简单的微服务架构

    前言 本篇仅作引导,内容较多,如果阅读不方便,可以使用电脑打开我们的文档官网进行阅读.如下图所示: 文档官网地址:docs.xin-lai.com 目录 总体介绍   微服务架构的好处    微服务架 ...

  8. 基于消息中间件RabbitMQ实现简单的RPC服务

    转载自  基于消息中间件RabbitMQ实现简单的RPC服务 RPC(Remote Procedure Call,远程过程调用),是一种计算机通信协议.对于两台机器而言,就是A服务器上的应用程序调用B ...

  9. 使用SpringBoot搭建一个简单的webSocket服务

    前言 个人地址:使用SpringBoot搭建一个简单的webSocket服务 什么是WebSocket? WebSocket是一个HTML5新增的协议,它的目的在浏览器和服务器之间建立一个不受限的双向 ...

最新文章

  1. 旅行商问题(Traveling Saleman Problem,TSP)
  2. iOS new 和 alloc的区别
  3. 图说数据中心空调系统原理和架构
  4. 法国spin高等计算机学校,法国顶尖“大矿”,一起去矿校挖矿吧!
  5. SpringCloud Greenwich(二)注册中心之consul、Zuul和 gateway网关配置
  6. 该错误是如何发生的? Git一分为二进行营救!
  7. 计算机组成原理 试讲,常州信息职业技术学院-试讲ppt-计算机组成原理-信息表示.ppt...
  8. [转载]Qt之获取本机网络信息_vortex_新浪博客
  9. 学习《医学三字经白话解》之隔食反胃(吞咽梗阻)
  10. 校招/社招-算法岗简历及面试经验分享
  11. algodoo是什么意思_洋是什么意思 带洋字的男孩名字 用洋字起名的寓意
  12. “地图易“制图工具——零代码制作漂亮业务地图
  13. Python采集股票数据信息
  14. java实现PDF转图片功能,附实例源码!
  15. 那些10万变百万的矿工,都是从选对挖矿币种开始的!
  16. 信号完整性之S参数(八)
  17. DELPHI中自定义消息的发送和接收
  18. 实验记录配置华为NAT Server
  19. html文本框怎么写表情,js文本框插入表情支持解析代码
  20. 〖产品思维训练白宝书 - 基础学科素养篇①〗- 哪些学科知识更有利于我们掌握产品思维?

热门文章

  1. OpenGL ktxview (KTX查看器)的实例
  2. C++栈内存与文字常量区
  3. C++数组与指针的区别
  4. QT的QLinkedListIterator类的使用
  5. c++STL算法基础
  6. 经典C语言程序100例之九
  7. android fragment动态加载,动态添加Fragment
  8. 54_pytorch GAN(生成对抗网络)、Gan代码示例、WGAN代码示例
  9. 4.关于QT中的QFile文件操作,QBuffer,Label上添加QPixmap,QByteArray和QString之间的区别,QTextStream和QDataStream的区别,QT内存映射(
  10. 1.CCProgressTo进度动作,条形进度条,扇形进度条