通過HttpListener實現簡單的Http服務


通過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 plain  copy
 
  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.   
  10.   
  11. namespace ConsoleApplication1  
  12. {  
  13.     class Program  
  14.     {  
  15.         static HttpListener sSocket = null;  
  16.           
  17.         static void Main(string[] args)  
  18.         {  
  19.             sSocket = new HttpListener();  
  20.             sSocket.Prefixes.Add("http://127.0.0.1:8080/");  
  21.             sSocket.Start();  
  22.             sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);  
  23.             Console.Read();              
  24.         }  
  25.   
  26.         static void GetContextCallBack(IAsyncResult ar)  
  27.         {  
  28.             try  
  29.             {  
  30.                 sSocket = ar.AsyncState as HttpListener;  
  31.                 HttpListenerContext context = sSocket.EndGetContext(ar);  
  32.    sSocket.BeginGetContext(new AsyncCallback(GetContextCallBack), sSocket);  
  33.      
  34.                 Console.WriteLine(context.Request.Url.PathAndQuery);  
  35.                   
  36.            //其它處理code  
  37.             }  
  38.             catch { }             
  39.         }  
  40.     }  
  41. }  

 

非異步方法listener


====== C# 利用HttpListener監聽處理Http請求 ======

[csharp]  view plain  copy
 
  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.   
  28.                             listerner.Start();  
  29.                         }  
  30.                         catch (Exception e)  
  31.                         {  
  32.                             Console.WriteLine("未能成功連接服務器.....");  
  33.                             listerner = new HttpListener();  
  34.                             continue;  
  35.                         }  
  36.                         break;  
  37.                     }  
  38.                     Console.WriteLine("服務器啟動成功.......");  
  39.   
  40.                     int maxThreadNum, portThreadNum;  
  41.   
  42.                     //線程池  
  43.                     int minThreadNum;  
  44.                     ThreadPool.GetMaxThreads(out maxThreadNum, out portThreadNum);  
  45.                     ThreadPool.GetMinThreads(out minThreadNum, out portThreadNum);  
  46.                     Console.WriteLine("最大線程數:{0}", maxThreadNum);  
  47.                     Console.WriteLine("最小空閑線程數:{0}", minThreadNum);  
  48.                       
  49.                     Console.WriteLine("\n\n等待客戶連接中。。。。");  
  50.                     while (true)  
  51.                     {  
  52.                         //等待請求連接  
  53.                         //沒有請求則GetContext處於阻塞狀態  
  54.                         HttpListenerContext ctx = listerner.GetContext();  
  55.   
  56.                         ThreadPool.QueueUserWorkItem(new WaitCallback(TaskProc), ctx);  
  57.                     }  
  58.                     con.Close();  
  59.                     listerner.Stop();  
  60.                 }  
  61.             }  
  62.             catch (Exception e)  
  63.             {  
  64.                 Console.WriteLine(e.Message);  
  65.                 Console.Write("Press any key to continue . . . ");  
  66.                 Console.ReadKey( );  
  67.             }  
  68.         }  
  69.   
  70.         static void TaskProc(object o)  
  71.         {  
  72.             HttpListenerContext ctx = (HttpListenerContext)o;  
  73.   
  74.             ctx.Response.StatusCode = 200;//設置返回給客服端http狀態代碼  
  75.          
  76.             string type = ctx.Request.QueryString["type"];  
  77.             string userId = ctx.Request.QueryString["userId"];  
  78.             string password = ctx.Request.QueryString["password"];  
  79.             string filename = Path.GetFileName(ctx.Request.RawUrl);  
  80.             string userName = HttpUtility.ParseQueryString(filename).Get("userName");//避免中文亂碼  
  81.   
  82.             //進行處理  
  83.               
  84.             //使用Writer輸出http響應代碼  
  85.             using (StreamWriter writer = new StreamWriter(ctx.Response.OutputStream))  
  86.             {  
  87.                 writer.Write(“處理結果”);  
  88.                 writer.Close();  
  89.                 ctx.Response.Close();  
  90.             }  
  91.         }  
  92.     }  
  93. }  



Android客戶端:

[java]  view plain  copy
 
  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.          
  12.         try {    
  13.         String content = "";  
  14.         String tmp   =   java.net.URLEncoder.encode(userName,   "utf-8");   //防止中文亂碼  
  15.         URL url = new URL(URL+"?type=Register&userId="+userId+"&password="+password+"&groupId="+groupId+"&userName="+tmp);     
  16.                // HttpURLConnection     
  17.                HttpURLConnection httpconn = (HttpURLConnection) url.openConnection();     
  18.        
  19.                if (httpconn.getResponseCode() == HttpURLConnection.HTTP_OK) {     
  20.                        
  21.                    InputStreamReader isr = new InputStreamReader(httpconn.getInputStream(), "utf-8");     
  22.                    int i;     
  23.                         
  24.                    // read     
  25.                    while ((i = isr.read()) != -1) {     
  26.                        content = content + (char) i;     
  27.                    }     
  28.                    isr.close();       
  29.                }     
  30.                //disconnect     
  31.                httpconn.disconnect();     
  32.   
  33.   
  34.     } catch (Exception e) {  
  35.     e.printStackTrace();  
  36.     }  
  37.        }//run  
  38. }).start();//thread  
  39. }  



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



=== ThreadHelper ===

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


=== end ===


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM