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 ======
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using DevSDK.Net.Sockets;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static HttpListener sSocket = null;
static void Main(string[] args)
{
sSocket = new HttpListener();
sSocket.Prefixes.Add("http://127.0.0.1:8080/");
sSocket.Start();
sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);
Console.Read();
}
static void GetContextCallBack(IAsyncResult ar)
try
{
sSocket = ar.AsyncState as HttpListener;
HttpListenerContext context = sSocket.EndGetContext(ar);
sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);
Console.WriteLine(context.Request.Url.PathAndQuery);
//其它处理code
}
catch { }
}
}
====== C# 利用HttpListener监听处理Http请求 ======
using System.Xml.Serialization;
using System.Threading;
using System.Web;
namespace Test
HttpListener listerner = new HttpListener();
{
for (; true; )
{
try
{
listerner.AuthenticationSchemes = AuthenticationSchemes.Anonymous;//指定身份验证 Anonymous匿名访问
listerner.Prefixes.Add("http://192.168.1.10:1500/ApiService/");
listerner.Start();
}
catch (Exception e)
Console.WriteLine("未能成功连接服务器.....");
listerner = new HttpListener();
continue;
break;
}
Console.WriteLine("服务器启动成功.......");
int maxThreadNum, portThreadNum;
//线程池
int minThreadNum;
ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum);
ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum);
Console.WriteLine("最大线程数:{0}", maxThreadNum);
Console.WriteLine("最小空闲线程数:{0}", minThreadNum);
Console.WriteLine("\n\n等待客户连接中。。。。");
while (true)
//等待请求连接
//没有请求则GetContext处于阻塞状态
HttpListenerContext ctx = listerner.GetContext();
ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc), ctx);
con.Close();
listerner.Stop();
}
catch (Exception e)
Console.WriteLine(e.Message);
Console.Write("Press any key to continue . . . ");
Console.ReadKey( );
static void TaskProc(object o)
HttpListenerContext ctx = (HttpListenerContext)o;
ctx.Response.StatusCode = 200;//设置返回给客服端http状态代码
string type = ctx.Request.QueryString["type"];
string userId = ctx.Request.QueryString["userId"];
string password = ctx.Request.QueryString["password"];
string filename = Path.GetFileName(ctx.Request.RawUrl);
string userName = HttpUtility.ParseQueryString(filename).Get("userName");//避免中文乱码
//进行处理
//使用Writer输出http响应代码
using (StreamWriter writer = new StreamWriter(ctx.Response.OutputStream))
writer.Write(“处理结果”);
writer.Close();
ctx.Response.Close();
Android客户端:
public static void Register(final Handler handler, final Context context,
final String userId, final String userName,final int groupId, final String password){
new Thread(new Runnable(){
public void run() {
if(!CommonTools.checkNetwork(context)){
Message msg = new Message();
msg.what = Signal.NETWORK_ERR;
handler.sendMessage(msg);
return;
try {
String content = "";
String tmp = java.net.URLEncoder.encode(userName, "utf-8"); //防止中文乱码
URL url = new URL(URL+"?type=Register&userId="+userId+"&password="+password+"&groupId="+groupId+"&userName="+tmp);
// HttpURLConnection
HttpURLConnection httpconn = (HttpURLConnection) url.openConnection();
if (httpconn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStreamReader isr = new InputStreamReader(httpconn.getInputStream(), "utf-8");
int i;
// read
while ((i = isr.read()) != -1) {
content = content + (char) i;
}
isr.close();
}
//disconnect
httpconn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}//run
}).start();//thread
注意:
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 自开线程处理请求 ======
namespace HttpHelper
/// <summary>
/// HTTP请求监听
/// </summary>
public class HttpListeners
private static HttpListener _httpListener;
static readonly int Port = 1005;
static HttpListeners()
ListenerStart();
private static bool ListenerStop()
if (_httpListener != null)
//LogInfo("停止监听端口:" + Port);
_httpListener.Stop();
return true;
//LogError(e.Message + e.StackTrace);
return false;
/// <summary>
/// 监听端口
/// </summary>
private static void ListenerStart()
_httpListener = new HttpListener { AuthenticationSchemes = AuthenticationSchemes.Anonymous };
_httpListener.Prefixes.Add(string.Format("http://+:{0}/",Port));
_httpListener.Start();
//LogInfo("开始监听端口:" + Port);
while (true)
try
//监听客户端的连接,线程阻塞,直到有客户端连接为止
var client = _httpListener.GetContext();
new Thread(HandleRequest).StartAsync(client);
catch (Exception ex)
//LogError(ex.Message + ex.StackTrace);
Environment.Exit(0);
private static void HandleRequest(object obj)
var client = obj as HttpListenerContext;
if (client == null) return;
var coding = Encoding.UTF8;
var request = client.Request;
// 取得回应对象
var response = client.Response;
response.StatusCode = 200;
response.ContentEncoding = coding;
Console.WriteLine("{0} {1} HTTP/1.1", request.HttpMethod, request.RawUrl);
Console.WriteLine("Accept: {0}", string.Join(",", request.AcceptTypes));
Console.WriteLine("Accept-Language: {0}",
string.Join(",", request.UserLanguages));
Console.WriteLine("User-Agent: {0}", request.UserAgent);
Console.WriteLine("Accept-Encoding: {0}", request.Headers["Accept-Encoding"]);
Console.WriteLine("Connection: {0}",
request.KeepAlive ? "Keep-Alive" : "close");
Console.WriteLine("Host: {0}", request.UserHostName);
Console.WriteLine("Pragma: {0}", request.Headers["Pragma"]);
// 构造回应内容
string responseString = @"<html><head><title>HttpListener Test</title></head><body><div>Hello, world.</div></body></html>";
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
//对客户端输出相应信息.
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
//关闭输出流,释放相应资源
output.Close();
finally
try
client.Response.Close();
catch (Exception e)
//LogError(e.Message);
=== ThreadHelper ===
using System.Threading.Tasks;
public static class ThreadHelper
/// 开启同步多线程
public static void StartSync(this IEnumerable<Thread> threads, object startPara = null, Func<object, object> callback = null)
var ts = threads.ToArray();
//启动线程
foreach (var thread in ts)
if (!thread.IsBackground)
thread.IsBackground = true;
var times = 0;
while (thread.ThreadState == (ThreadState.Background | ThreadState.Unstarted) && times < 10)
if (startPara == null)
thread.Start();
else
thread.Start(startPara);
catch (Exception e)
times++;
Thread.Sleep(100);
Thread.Sleep(2000);
//等待全部结束
thread.Join();
if (callback != null)
callback(startPara);
/// 开启多线程
public static void StartAsync(this IEnumerable<Thread> threads, object startPara = null, Func<object, object> callback = null)
times++;
/// 开启同步线程
public static void StartSync(this Thread thread, object parameter = null)
if (parameter == null)
thread.Start();
else
thread.Start(parameter);
Thread.Sleep(1000);
thread.Join();
/// 开启带超时的同步线程
public static void StartSyncTimeout(this Thread thread, int timeoutSeconds, object parameter = null)
thread.Join(timeoutSeconds * 1000);
/// 开启异步线程
public static void StartAsync(this Thread thread, object parameter = null)
=== end ===