這裡我們通過HTTPListener類實現了一個非常簡單的WEB伺服器。也使用了TCPLISTENER類進行TCP套接字I/O操作。我們配置了監聽器接收任何主機到本地機器1234埠的連接。然後在單獨的工作線程中啟動這個監管器,從而在主線程中可以控制這個監聽器。 當使用GetConte... ...
二、 編寫一個非同步的HTTP伺服器和客戶端
本節展示瞭如何編寫一個簡單的非同步HTTP伺服器。
1.程式代碼如下。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace ThreadIODemo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("--創建簡單Web服務示例 -- ");
var server = new AsyncHttpServer(port: 1234);
var t = Task.Run(() => server.Start());
Console.WriteLine("Listening on port 1234.在瀏覽器中打開http://localhost:1234 ");
Console.WriteLine("測試連接");
Console.WriteLine();
GetResponseAsync("http://localhost:1234").GetAwaiter().GetResult();
Console.WriteLine();
Console.WriteLine("輸入回車鍵,停止服務");
Console.ReadLine();
string msg= server.Stop().GetAwaiter().GetResult();
Console.WriteLine(msg);
Console.Read();
}
static async Task GetResponseAsync(string url)
{
using (var client = new HttpClient())
{
HttpResponseMessage responseMessage = await client.GetAsync(url);
string responseHeaders = responseMessage.Headers.ToString();
string response = await responseMessage.Content.ReadAsStringAsync();
Console.WriteLine("Response Headers:");
Console.WriteLine(responseHeaders);
Console.WriteLine("Response Body:");
Console.WriteLine(response);
}
}
}
class AsyncHttpServer
{
readonly HttpListener _listener;
const string RESPONSE_TEMPLATE = "<html><head><title>Test</title></head>
<body><h2>Test Page </h2><h4>ToDay is:{0}</h4></body></html>";
public AsyncHttpServer(int port)
{
_listener = new HttpListener();
_listener.Prefixes.Add(string.Format("http://+:{0}/", port));
}
public async Task Start()
{
_listener.Start();
while (true)
{
var ctx = await _listener.GetContextAsync();
Console.WriteLine("{0} Client connected...",DateTime.Now.ToString());
string response = string.Format(RESPONSE_TEMPLATE, DateTime.Now);
using (var sw = new StreamWriter(ctx.Response.OutputStream))
{
await sw.WriteAsync(response);
await sw.FlushAsync();
}
}
//return string.Format("監聽服務開始 {0} ", DateTime.Now.ToString());
}
public async Task<string> Stop()
{
_listener.Stop();
Console.WriteLine("監聽停止,停止服務");
await Task.Delay(TimeSpan.FromSeconds(2));
return string.Format("監聽服務停止 {0} ",DateTime.Now.ToString());
}
}
}
2.http服務啟動如下圖。
3.在瀏覽器中輸入http://localhost:1234,之後如下圖1。在等30秒之後,再次刷新,如下圖中的2.
4.在http的web服務程式中可以看到瀏覽器訪問了伺服器兩次。如下圖中的紅框。
4.在http的web服務程式中輸入回車,則服務會停止 。如下圖中的紅框。
這裡我們通過HTTPListener類實現了一個非常簡單的WEB伺服器。也使用了TCPLISTENER類進行TCP套接字I/O操作。我們配置了監聽器接收任何主機到本地機器1234埠的連接。然後在單獨的工作線程中啟動這個監管器,從而在主線程中可以控制這個監聽器。
當使用GetContextAsync方法時會發生非同步I/O操作。可惜的是,其並不接收CancellationToken從而實現取消功能。所以如果想關閉這個伺服器,只需要調用 _listenter.Abort方法,這將丟棄所有連接並關閉伺服器。
為了對這個伺服器執行一個非同步請求,我們使用了統一命名空間下的System.Net.Http集合中的HttpClient類。我們使用Get.Async方法來發起一個非同步的Http Get請求。還有其他的方法用於發起其他的HTTP請求,比如POST,DELETE,PUT。HttpClient還有很多其他的選項,比如使用不同的格式(比如XML和JSON)來序列化和反序列化對象,指定代理伺服器地址,認證以及其他配置。
當運行這個程式時,可以看到這個伺服器被啟動起來。在伺服器端代碼中,我們使用GetContextAsync方法來接收新的客戶端連接。當有新的客戶端連接時這個方法就會返回。我們簡單的輸出一個包含當前日期和時間的非常基礎的HTML作為響應。然後我們請求服務並列印響應頭和內容。