Phần này tìm hiểu tạo ra một máy chủ HTTP đơn giản với lớp HttpListener. Thường thì, để có đầy đủ các tính năng khi triển khai ứng dụng chúng ta có thể sử dụng dịch vụ HTTP hoàn chỉnh như IIS, Apache HTTPD, Nginx hay Kestrel. Tuy vậy, để nhanh chóng có thể tạo dịch vụ lắng nghe các yêu cầu HTTP gửi đến và trả về Respone thích hợp thì dùng đến HttpListener

Lớp HttpListener

Lớp HttpListener giúp tạo ra dịch vụ với giao thức HTTP, nó lắng nghe các yêu cầu HTTP gửi đến và trả về HTTP Respone. Dịch vụ HTTP hoạt động và tồn tại cùng với sự tồn tại của đối tượng HttpListener. Để sử dụng HttpListener, cần khởi tạo đối tượng này sau đó thiết lập thuộc tính Prefixes cho nó, thuộc tính này là tập hợp các chuỗi cho biết URI mà HttpListener sử dụng.

Một số phương thức thuộc tính của lớp HttpListenr

Thành viên Diễn tả
IsSupported Phương thức tĩnh kiểu bool, cho biết máy có hỗ trợ HttpListener hay không
Prefixes Thuộc tính, nó chứa các chuỗi cấu trúc URI mà HttpListener làm việc. Ví dụ để nó làm việc trên cổng 8080, giao thức http:// thì chuỗi đó là http://*:8080/ và làm việc trên cổng 443 thì chuỗi là https://*/
HttpListener listener = new HttpListener();
listener.Prefixes.Add("http://*:8080/");
listener.Prefixes.Add("https://*/");
Start() Bắt đầu cho phép nhận các yêu cầu (HTTP Request) gửi đến.
Stop() Dừng dịch vụ
GetContextAsync() Chờ kết tạo một kết nối client gửi đến và thực hiện bất đồng bộ nhận thông tin gửi đến bởi client nếu có. Trả về Task với thuộc tính Result khi kết thúc là đối tượng kiểu HttpListenerContext chứa thông tin gửi đến (request) và thông tin sẽ trả về response, khi đối tượng này huỷ thì respone sẽ trả về cho clien truy cập.
HttpListenerContext   context  = await listener.GetContextAsync();
HttpListenerRequest   request  = context.Request; // chứa thông tin gửi đến
HttpListenerResponse  response = context.Response;// các nội dung trả về thiết lập vào respone

Ví dụ tạo máy chủ HTTP đơn giản bằng HttpListener

Source Code

using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Text;

namespace HttpListenerExample
{
 
    class Program
    {    
        // Sinh mảng byte, chứa nội dung HTML sẽ trả về
        public static byte[] GetHtmlPage(HttpListenerRequest request) {
            string format = @"<!DOCTYPE html>
                                <html lang=""en""> 
                                    <head><meta charset=""UTF-8"">{0}</head> 
                                    <body>{1}</body> 
                                </html>";
            string head = "<title>Test WebServer</title>";
            var body = new StringBuilder();
            body.Append("<h1>Request Info</h1>");
            body.Append("<h2>Request Header:</h2>");
            
            // Header infomation
            var headers = from key in request.Headers.AllKeys 
                    select $"<div>{key} : {string.Join(",", request.Headers.GetValues(key))}</div>";
            body.Append(string.Join("", headers));

            //Extract request properties
            body.Append("<h2>Request properties:</h2>");
            var properties = request.GetType().GetProperties();
            foreach (var property in properties)
            {
                var name_pro = property.Name;
                string value_pro;
                try {
                    value_pro = property.GetValue(request).ToString();
                }
                catch (Exception e)  {
                    value_pro = e.Message;
                }
                body.Append($"<div>{name_pro} : {value_pro}</div>");
                
            };
            string html = string.Format(format, head, body.ToString());                    
            return Encoding.UTF8.GetBytes(html);
        }
        
        // Tạo và chạy một HttpListener (Async)
        public static async Task RunWebserverAsync(params string[] prefixes) {
            if (!HttpListener.IsSupported)
                throw new Exception("Máy không hỗ trợ HttpListener.");
            if (prefixes == null || prefixes.Length == 0) 
                throw new ArgumentException("prefixes");
            HttpListener listener = new HttpListener();
            
            foreach (string s in prefixes)
            {
                listener.Prefixes.Add(s);
            }
            Console.WriteLine("Server start ...");
            listener.Start();
            
            do {
                HttpListenerContext     context  = await listener.GetContextAsync();
                HttpListenerRequest     request  = context.Request;
                HttpListenerResponse    response = context.Response;
                
                // Thiết lập kiểu tài liệu trả về và mã trả về
                context.Response.Headers.Add("content-type",  "text/html");
                context.Response.StatusCode = (int)HttpStatusCode.OK;
                
                // Ghi nội dung trả về vào Content
                byte[] buffer               = GetHtmlPage(context.Request);
                response.ContentLength64    = buffer.Length;
                System.IO.Stream output     = response.OutputStream;
                await output.WriteAsync(buffer,0,buffer.Length); 
            } while (true);
            //  listener.Stop();    

        }

        static async Task  Main(string[] args)
        {
            // Chạy HttpListener lắng nghe ở cổng 8080
            await RunWebserverAsync(new string[] {"http://*:8080/"});
            Console.ReadKey();
        }

    }
}

Truy cậ thử với http://localhost:8080

Đăng ký theo dõi ủng hộ kênh