C # implements one of the simplest HTTP servers

Source: Internet
Author: User

Introduction

This article implements the simplest HTTP server class in C #, you can embed it in your own project, or you can read the code to learn about the HTTP protocol.

background

High-performance Web applications are typically built on powerful Web servers, such as IIS, Apache, and Tomcat. However, HTML is a very flexible UI markup language, which means that any application and backend services can provide HTML generation support. In this small example, a server like IIS, Apache, consumes too much resources, and we need to implement a simple HTTP server to embed it in our app to handle Web requests. We just need a class to do it, it's simple.

Code Implementation

First, let's review how to use the class, and then we'll analyze the specifics of the implementation. Here we create a class that inherits from Httpserver and implements the two abstract methods of Handlegetrequest and Handlepostrequest:

  1. public class Myhttpserver:httpserver {

  2. public myhttpserver (int port)

  3. : Base (port) {

  4. }

  5. public override void Handlegetrequest (Httpprocessor p) {

  6. Console.WriteLine ("Request: {0}", P.http_url);

  7. P.writesuccess ();

  8. P.outputstream.writeline ("

  9. P.outputstream.writeline ("Current time:" + DateTime.Now.ToString ());

  10. P.outputstream.writeline ("URL: {0}", P.http_url);


  11. P.outputstream.writeline ("<form method=post action=/form>");

  12. P.outputstream.writeline ("<input type=text name=foo value=foovalue>");

  13. P.outputstream.writeline ("<input type=submit name=bar value=barvalue>");

  14. P.outputstream.writeline ("</form>");

  15. }


  16. public override void Handlepostrequest (Httpprocessor p, StreamReader inputdata) {

  17. Console.WriteLine ("POST request: {0}", P.http_url);

  18. String data = Inputdata.readtoend ();


  19. P.outputstream.writeline ("

  20. P.outputstream.writeline ("<a href=/test>return</a><p>");

  21. P.outputstream.writeline ("Postbody: <pre>{0}</pre>", data);

  22. }

  23. }

Copy Code

When we start processing a simple request, we need to start a thread individually to listen on a port, such as port 8080:
    1. Httpserver httpserver = new Myhttpserver (8080);

    2. Thread thread = new Thread (new ThreadStart (Httpserver.listen));

    3. Thread. Start ();

Copy Code

If you compile and run this project, you will see the sample content generated on the page under the browser http://localhost:8080 address. Let's take a quick look at how this HTTP server engine is implemented.

This Web server consists of two components, one is the Httpserver class that initiates TcpListener to listen on the specified port, and the TCP connection request is cycled with the AcceptTcpClient () method, which is the first step in processing a TCP connection. Then the request arrives at the specified port, and a new pair of ports is created to initialize the client-to-server TCP connection. This pair of ports is the TcpClient session, so that we can keep our main port to continue to receive new connection requests. From the code below we can see that each listener creates a new Tcpclien,httpserver class and creates a new httpprocessor, and then starts a thread to operate. The Httpserver class also contains two abstract methods, and you must implement both methods.

  1. Public abstract class Httpserver {


  2. protected int port;

  3. TcpListener Listener;

  4. bool is_active = true;


  5. public httpserver (int port) {

  6. This.port = port;

  7. }


  8. public void Listen () {

  9. Listener = new TcpListener (port);

  10. Listener. Start ();

  11. while (is_active) {

  12. TcpClient s = listener. AcceptTcpClient ();

  13. Httpprocessor processor = new Httpprocessor (s, this);

  14. Thread thread = new Thread (new ThreadStart (processor.process));

  15. Thread. Start ();

  16. Thread.Sleep (1);

  17. }

  18. }


  19. public abstract void Handlegetrequest (Httpprocessor p);

  20. public abstract void Handlepostrequest (Httpprocessor p, StreamReader inputdata);

  21. }

Copy Code

In this way, a new TCP connection is httpprocessor in its own thread, and Httpprocessor's job is to properly parse the HTTP header and control the correct implementation of the abstract method. Let's take a look at the HTTP header processing, the first line of the HTTP request is as follows:
    1. Get/myurl http/1.0

Copy Code

After the input and output of process () is set, Httpprocessor calls the Parserequest () method.
    1. public void Parserequest () {

    2. String request = Inputstream.readline ();

    3. String[] tokens = Request. Split (');

    4. if (tokens. Length! = 3) {

    5. throw new Exception ("Invalid HTTP request line");

    6. }

    7. Http_method = Tokens[0]. ToUpper ();

    8. Http_url = tokens[1];

    9. http_protocol_versionstring = tokens[2];


    10. Console.WriteLine ("Starting:" + request);

    11. }

Copy Code

The HTTP request consists of 3 parts, so we just need to use string. The split () method splits them into 3 parts, then receives and parses HTTP header information from the client, each row of data in the header is saved as Key-value (key-value), and a blank line represents the HTTP header information end flag. Our code uses the Readheaders method to read the HTTP header information:
  1. public void Readheaders () {

  2. Console.WriteLine ("Readheaders ()");

  3. String Line;

  4. while (line = Inputstream.readline ()) = null) {

  5. if (line. Equals ("")) {

  6. Console.WriteLine ("Got Headers");

  7. Return

  8. }


  9. int separator = line. IndexOf (': ');

  10. if (separator = =-1) {

  11. throw new Exception ("Invalid HTTP header line:" + line);

  12. }

  13. String name = line. Substring (0, separator);

  14. int pos = separator + 1;

  15. while (Pos < line. Length) && (line[pos] = = ")) {

  16. pos++; Filter out all spaces

  17. }


  18. String value = line. Substring (POS, line. Length-pos);

  19. Console.WriteLine ("Header: {0}:{1}", Name,value);

  20. Httpheaders[name] = value;

  21. }

  22. }

Copy Code

Here, we have learned how to handle simple get and post requests, which are assigned to the correct handler handler, respectively. In this case, there is a tricky problem with sending the data, which is that the request header information contains the length information of the sending data content-length, when we want the Handlepostrequest method in the subclass Httpserver to handle the data correctly, We need to put the data length content-length information into the data stream, otherwise the sending side waits for data that is never going to arrive and blocking. We used a seemingly less elegant but very efficient way to handle this situation by reading the data into the MemoryStream before sending the data to the post processing method. This is not ideal, for the following reasons: If the data sent is large, or even uploading a file, then it is not appropriate or impossible for us to cache the data in memory. The ideal method is to limit the length of the post, for example, we can limit the length of the data to 10MB.

Another simplification of this simple version of the HTTP server is the return value of Content-type, in which the server always sends the mime-type of the data to the client, telling the client what type of data it needs to receive. In the Writesuccess () method, we see that the server always sends the text/html type, and if you need to add other types, you can extend this method.


C # implements one of the simplest HTTP servers

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.