程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 基於C#完成一個最簡略的HTTP辦事器實例

基於C#完成一個最簡略的HTTP辦事器實例

編輯:C#入門知識

基於C#完成一個最簡略的HTTP辦事器實例。本站提示廣大學習愛好者:(基於C#完成一個最簡略的HTTP辦事器實例)文章只能為提供參考,不一定能成為您想要的結果。以下是基於C#完成一個最簡略的HTTP辦事器實例正文


本文具體剖析了基於C#完成一個最簡略的HTTP辦事器的辦法。分享給年夜家供年夜家參考。詳細以下:

1、簡介

本文用C#完成了一個最簡略的HTTP辦事器類,你可以將它嵌入到本身的項目中,或許也能夠浏覽代碼來進修關於HTTP協定的常識。

2、配景

高機能的WEB運用普通都架設在壯大的WEB辦事器上,例如IIS, Apache, 和Tomcat。但是,HTML長短常靈巧的UI標志說話,也就是說任何運用和後端辦事都可以供給HTML的生成支撐。在這個小小的例子中,像IIS,、 Apache如許的辦事器消費的資本太年夜了,我們須要本身完成一個簡略的HTTP辦事器,將它嵌入到我們的運用頂用來處置WEB要求。我們僅須要一個類就 可以完成了,很簡略。

3、代碼完成

起首我們往返顧一下若何應用類,然後我們再來剖析完成的詳細細節。這裡我們創立了一個繼續於HttpServer的類,並完成了handleGETRequest 和handlePOSTRequest  這兩個籠統辦法:
public class MyHttpServer : HttpServer {
    public MyHttpServer(int port)
        : base(port) {
    }
    public override void handleGETRequest(HttpProcessor p) {
        Console.WriteLine("request: {0}", p.http_url);
        p.writeSuccess();
        p.outputStream.WriteLine("<html><body><h1>test server</h1>");
        p.outputStream.WriteLine("Current Time: " + DateTime.Now.ToString());
        p.outputStream.WriteLine("url : {0}", p.http_url);
 
        p.outputStream.WriteLine("<form method=post action=/form>");
        p.outputStream.WriteLine("<input type=text name=foo value=foovalue>");
        p.outputStream.WriteLine("<input type=submit name=bar value=barvalue>");
        p.outputStream.WriteLine("</form>");
    }
 
    public override void handlePOSTRequest(HttpProcessor p, StreamReader inputData) {
        Console.WriteLine("POST request: {0}", p.http_url);
        string data = inputData.ReadToEnd();
 
        p.outputStream.WriteLine("<html><body><h1>test server</h1>");
        p.outputStream.WriteLine("<a href=/test>return</a><p>");
        p.outputStream.WriteLine("postbody: <pre>{0}</pre>", data);
    }
}

當開端處置一個簡略的要求時,我們就須要零丁啟動一個線程來監聽一個端口,好比8080端口:
HttpServer httpServer = new MyHttpServer(8080);
Thread thread = new Thread(new ThreadStart(httpServer.listen));
thread.Start();

假如你編譯運轉這個項目,你會在閱讀器http://localhost:8080地址下看到頁面上生成的示例內容。讓我們來簡略看一下這個HTTP辦事器引擎是怎樣完成的。

這個WEB辦事器由兩個組件組成,一個是擔任啟動TcpListener來監聽指定端口的HttpServer類,而且用 AcceptTcpClient()辦法輪回處置TCP銜接要求,這是處置TCP銜接的第一步。然後要求達到“已指定“的端口,接著就會創立一對新的端 口,用來初始化客戶端到辦事器真個TCP銜接。這對端口就是TcpClient的session,如許便可以堅持我們的主端口可以持續吸收新的銜接要求。 從上面的代碼中我們可以看到,每次監聽法式都邑創立一個新的TcpClien,HttpServer類又會創立一個新的HttpProcessor,然 後啟動一個線程來操作。HttpServer類中還包括兩個籠統辦法,你必需完成這兩個辦法。
public abstract class HttpServer {
    protected int port;
    TcpListener listener;
    bool is_active = true;
 
    public HttpServer(int port) {
        this.port = port;
    }
 
    public void listen() {
        listener = new TcpListener(port);
        listener.Start();
        while (is_active) {               
            TcpClient s = listener.AcceptTcpClient();
            HttpProcessor processor = new HttpProcessor(s, this);
            Thread thread = new Thread(new ThreadStart(processor.process));
            thread.Start();
            Thread.Sleep(1);
        }
    }
 
    public abstract void handleGETRequest(HttpProcessor p);
    public abstract void handlePOSTRequest(HttpProcessor p, StreamReader inputData);
}

如許,一個新的tcp銜接就在本身的線程中被HttpProcessor處置了,HttpProcessor的任務就是准確解析HTTP頭,而且掌握准確完成的籠統辦法。上面我們來看看HTTP頭的處置進程,HTTP要求的第一行代碼以下:

GET /myurl HTTP/1.0

在設置完process()的輸出和輸入後,HttpProcessor就會挪用parseRequest()辦法。
public void parseRequest() {
    String request = inputStream.ReadLine();
    string[] tokens = request.Split(' ');
    if (tokens.Length != 3) {
        throw new Exception("invalid http request line");
    }
    http_method = tokens[0].ToUpper();
    http_url = tokens[1];
    http_protocol_versionstring = tokens[2];
 
    Console.WriteLine("starting: " + request);
}

HTTP要求由3部門構成,所以我們只須要用string.Split()辦法將它們朋分成3部門便可,接上去就是吸收息爭析來自客戶真個HTTP頭 信息,頭信息中的每行數據是以Key-Value(鍵-值)情勢保留,空行表現HTTP頭信息停止標記,我們代碼頂用readHeaders辦法來讀取 HTTP頭信息:
public void readHeaders() {
    Console.WriteLine("readHeaders()");
    String line;
    while ((line = inputStream.ReadLine()) != null) {
        if (line.Equals("")) {
            Console.WriteLine("got headers");
            return;
        }
 
        int separator = line.IndexOf(':');
        if (separator == -1) {
            throw new Exception("invalid http header line: " + line);
        }
        String name = line.Substring(0, separator);
        int pos = separator + 1;
        while ((pos < line.Length) && (line[pos] == ' ')) {
            pos++; // 過濾失落一切空格
        }
 
        string value = line.Substring(pos, line.Length - pos);
        Console.WriteLine("header: {0}:{1}",name,value);
        httpHeaders[name] = value;
    }
}

到這裡,我們曾經懂得了若何處置簡略的GET和POST要求,它們分離被分派給准確的handler處置法式。在本例中,發送數據的時刻有一個辣手的 成績須要處置,那就是要求頭信息中包括發送數據的長度信息content-length,當我們願望子類HttpServer中的 handlePOSTRequest辦法可以或許准確處置數據時,我們須要將數據長度content-length信息一路放入數據流中,不然發送端會由於等 待永久弗成能達到的數據和壅塞期待。我們用了一種看起來不那末優雅但異常有用的辦法來處置這類情形,行將數據發送給POST處置辦法前先把數據讀入到 MemoryStream中。這類做法不太幻想,緣由以下:假如發送的數據很年夜,乃至是上傳一個文件,那末我們將這些數據緩存在內存就不那末適合乃至是不 能夠的。幻想的辦法是限制post的長度,好比我們可以將數據長度限制為10MB。

這個簡略單純版HTTP辦事器另外一個簡化的處所就是content-type的前往值,在HTTP協定中,辦事器老是會將數據的MIME-Type發送給 客戶端,告知客戶端本身須要吸收甚麼類型的數據。在writeSuccess()辦法中,我們看到,辦事器老是發送text/html類型,假如你須要加 入其他的類型,你可以擴大這個辦法。

願望本文所述對年夜家的C#法式設計有所贊助。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved