TCP/IP protocol learning (iv) Web server---Static resource processing based on C # socket

Source: Internet
Author: User
Tags password protection

Directory

1. C # Socket Communication

2. HTTP parsing engine

3. Resource reads and returns

4. Server Testing and code download

A Web server is the host of a Web resource that handles requests from a client browser and specifies that the corresponding Web resource be returned to the user, including not only HTML files, JS scripts, JPG images, but also dynamic content generated by the software. To meet the above requirements, a complete Web server workflow:

1) The server obtains the HTTP request packets that the browser sends to the server through a TCP/IP connection.

2) HTTP request through the Web server's HTTP parsing engine analysis of the request method, resource address and other information, and then start processing.

3) for a static request, the request URL path file is queried on the server and returned (404 no Found if not found).

4) involving dynamic requests, such as CGI, AJAX, ASP , and so on, according to the HTTP method, take different processing.

  

The core of Web server consists of C # socket communication, HTTP parsing engine, static resource file lookup, dynamic Data receiving and sending 4 parts, this section mainly implements the first 3 parts because of the reason of personal writing progress (that is, the Web server that can query the static resources), Dynamic Data processing because of the processing methods involved in the Cgi,ajax,asp method, after completion in the summary of relevant knowledge.

1. C # Socket Communication

C # sockets are encapsulated by the TCP/IP protocol to implement APIs that meet TCP traffic. In b/S architecture, server-side processing and C/s connection is basically the same, the main work includes: Create socket sockets, listen to connections, establish connections, get requests, process and return data, close connections and so on.

Program entry function, using polling method to implement the listener to the client request.

          Create a listener thread thread          listen_thread = new Thread (socket_listen);          Listen_thread. IsBackground = false;          Listen_thread. Start ();        

Listen to threads, create socket sockets, bind and listen to the specified port, wait for connection to be established, after the connection is established, take into account the high concurrency of Web requests, and use another thread to process the established connection, thus implementing the concurrent server mode.

            Socket server_socket = null;            Listen to the IP address and port as a server, bind only the native IP address or loopback address (cannot conflict with other system process port)//If bound to this section IP address, other devices under the LAN can access the current server through Http://host:port            String host = "127.0.0.1";            int port = 3000;            IPAddress IP = ipaddress.parse (host);            IPEndPoint ipe = new IPEndPoint (IP, port); Creates a new socket socket, binds to the specified port and starts listening Server_socket = new socket (addressfamily.internetwork, SocketType.Stream, Protocolt Ype.            TCP); Server_socket.            Bind (IPE); Server_socket.            Listen (100); Console.WriteLine ("Server Binding at" + Host + ":" + port.)            ToString () + "...");            Console.WriteLine ("Wait for Connect ....");                while (true) {Socket currentsocket; Three times handshake succeeded, create a new connection Currentsocket = Server_socket.                Accept ();                Console.WriteLine ("New TCP Socket Create ..."); A single thread is used to process server transceiver, concurrent server mode Parameterizedthreadstart Tstart = new Parameterizedthreadstart (socket_process);                Thread process_thread = new Thread (Tstart); Process_thread.                IsBackground = false; Process_thread.            Start (Currentsocket); }

Connection processing, socket processing is mainly responsible for receiving the data generated by the connection, and the HTTP engine processing data submitted to the client browser.

          Socket Currentsocket = (socket) obj;          Try          {                string recvstr = "";                byte[] recvbytes = new byte[2000];                int length;                Obtain data transmitted by the current socket connection and convert to ASCII code format                length = currentsocket.receive (recvbytes, recvbytes.length, 0);                Recvstr = Encoding.ASCII.GetString (recvbytes, 0, length);                HTTP engine processing, returns data                byte[] bs =  http_engine (recvstr, length);                the Data currentsocket.send (BS, BS) is processed by the socket sending engine. Length, 0);                Console.WriteLine ("File Send Finish, Socket close....\r\n");                Close the socket Connection                currentsocket.close ();            }            catch (Exception Exception)            {                Console.WriteLine (Exception);                Currentsocket.close ();            }

C # Socket Communication architecture is no different from the C/s structure, if you know the socket can easily implement the above socket communication architecture. But the following section will describe the implementation of the Web Server Core--http parsing engine, which is the B/s architecture and C/S architecture server-side the biggest difference.

2. HTTP parsing engine

The Web server mainly implements the processing of the browser request packet, and returns the specified HTTP resource or data, which is implemented by the HTTP parsing engine, and before the HTTP parsing engine is written, we need to know what data is received for subsequent processing. Here are the HTTP request packages crawled via Wireshark:

Although the content of the HTTP request package is many, but because of the current implementation of less functionality, so only the first line of attention to the HTTP message can be, and the header field can be directly discarded non-processing, follow-up if using authentication mechanism, such as whitelist, blacklist filter, account/password protection, resource rights management, etc., the header still has to deal

For the start line of the HTTP message, the interior is separated by space and separated by ' \ r \ n ' as the end and header. Where Get:http method, '/': Resource path URL, http/1.1: protocol version, referring to HTTP authoritative Guide content, HTTP protocol common methods have get, PUT, DELETE, POST, head these 5 kinds, The static servers in this section mainly involve the Get method. After knowing how to parse the HTTP request message, we first define an HTTP message parsing structure for storing to the parsed information.

        public class Httpprase        {           //http method public           string Http_method;           HTTP resource public           string URL;           HTTP version number public           string version;           URL-resolved Request Web page type public a           string type;        };

Now we're going to start using the string method provided by C # to intercept HTTP messages to initialize the parameters in the above structure.

            int pos;           Based on \ r \ n Truncation, the HTTP header is obtained and converted to lowercase to facilitate subsequent processing           //get/http/1.1/r/n           pos = str. IndexOf ("\ r \ n");           string str_head = str. Substring (0, POS);           Str_head = Str_head. ToLower ();            Truncate the starting line according to ', and assign a value to the corresponding parameter           string[] arr = regex.split (Str_head, @ "\s+");           Httpserver.httpprase http_head = new Httpserver.httpprase ();           Http_head.http_method = arr[0];      "Get"           http_head.url = arr[1];              "/"           http_head.version = arr[2];          "http/1.1"            //Determines whether there is dynamic Data Http_head.ajax_status = Str_head that are obtained or submitted through AJAX requirements            . IndexOf (". Ajax")! =-1? True:false;           byte[] bs = Http_head.ajax_status = = true? Ajax_process (Http_head, str): static_process (Http_head, str);           return BS;

The following data can be submitted to the backend interface for processing. Because Dynamic Web-page processing requires a combination of both the web and the backend, the workload is large, so this section mainly describes the implementation of static Web page requests.

3. Resource reads and returns

A LAN Web request is typically accessed directly from the server through the Ip+port mode, so the first received request URL is '/', when we need to map it to the service-side location of the Access home page, currently set to index.html, for other requests, the value of the URL is generally '/xxx /xxx.js ", '/xxx/xxx.jpg" and so on, while reading in the server we need to define an absolute address, so also to add the root address of the resource store, currently the program is currently located in the folder +html as the root address of the resource, and the data path stored by the operating system is \xxx\xxx.js, so the URL data in the request is also replaced with ' \ \ ' (to ensure that the escape character can be converted to a path character, you need to use ' \ \ ' to represent the actual ' \ '), Also, in order to return the correct content-type field for subsequent HTTP response messages, there is a intercept '. ' field to get the type of the requested file.

              Get the folder where the current program is located              string url_str = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;              if (string. Compare (Head.url, "/") = = 0)              {                 //for the first request 127.0.0.1:3000/return index.html                 url_str + = "html\\index.html";                 Head.type = "html";              }              else              {                 //other requests such as/spring.js are replaced with ... \html\spring.js easy C # query file path                 url_str =url_str + "html\\" + Head.url.Substring (1);                 Url_str = Url_str. Replace ('/', ' \ \ ');                 int pos = Url_str. IndexOf ('. ');                Gets the current requested page type                 Head.type = url_str. Substring (pos + 1);              }

To this end, complete the entire HTTP parsing process, including the HTTP method, URL resource address obtained and converted to the Windows system path, the protocol version obtained three parts. For static Web requests, follow-up is relatively simple, query the system path under the resources, through the file stream opened, and in the form of character stream in memory, as the body of the HTTP response message part.

             Opens the file using the specified path in a file stream             (FileStream fs = new FileStream (Url_str, FileMode.Open, FileAccess.Read))             {                  // StreamReader temp = new StreamReader (FS, encoding.default);                  int fslen = (int) fs. Length;                  byte[] Fbyte = new Byte[fslen];                  int r = fs. Read (fbyte, 0, Fslen);                  Fs. Close ();                                 //......            }    

After the file is opened successfully, we will generate the HTTP response message, the HTTP response message and the request message is the same, also composed of three parts.

Status code: Provides a convenient way for clients to understand the results of transactional processing. The main implementations are:

  http/1.1 The request is not a problem, the body part of the entity contains the requested resource

http/1.1 Bad Request notifies the client that it sent an error

  http/1.1 401 Unauthorized is returned with the appropriate header to notify the client to perform the appropriate authentication

http/1.1 404 No Found indicates that the server could not find the requested URL

Response header: Providing the client with additional information about the server, the implementation of this project is relatively simple:

content-type:currenttype\r\n

Server:c# web\r\n

content-length:currentlength\r\n

Connection:close

Where Contenet-type needs to be replaced by the type types we have obtained above, here is a description of common substitution rules.

The Content-length field is the length of the HTTP response message body, that is, we obtain the total length of the resource (Fslen above), finally, the status code, response header and body data together through the socket sent to the client, the implementation of the entire process of the static server.

                            String http_current_head = HTTPServer.HTTP_OK_Head.Replace ("Currentlength", Convert.ToString (f                            Slen));                            Depending on the URL you need to return different header types specific comparison see http://tool.oschina.net/commons switch (head.type) {case "jpg": Http_current_head = Http_current_                                    Head.replace ("Currenttype", "application/x-jpg");                                Break                                    Case "png": Http_current_head = Http_current_head.replace ("Currenttype", "image/png");                                Break                                     Case "html": Http_current_head = Http_current_head.replace ("Currenttype", "text/html");                                Break Case "gif": Http_current_head = Http_current_head.Replace ("Currenttype", "image/gif");                                Break Case "JS": Http_current_head = Http_current_head.replace ("Currenttype", "application/x-                                    JavaScript ");                                Break                                    Case "ASP": Http_current_head = Http_current_head.replace ("Currenttype", "text/asp");                                Break                                    Default:http_current_head = Http_current_head.replace ("Currenttype", "text/html");                            Break                            } send_str = Httpserver.http_ok_start + http_current_head; byte[] Head_byte = new Byte[send_str.                            Length];                            Head_byte = Encoding.UTF8.GetBytes (SEND_STR); String streams are merged to generateSend file//before using byte[]->string, string merge, string->byte[], this method reads the picture garbled So modify to, string merge, string->byte[], byte[] Merge mode, read picture success byte[] Send_byte = new Byte[send_str. Length + fbyte.                            Length]; Buffer.blockcopy (head_byte, 0, send_byte, 0, Head_byte.                            Length); Buffer.blockcopy (fbyte, 0, Send_byte, Head_byte. Length * sizeof (BYTE), Fbyte.                            Length);                            Console.WriteLine ("File Send ...."); return send_byte;

4. Server Testing and code download

So far, a simple static Web server has been implemented, the resource files you want to access into the current program folder/html/ , and the first page is defined as index.html, open the server program, browser input HTTP// 127.0.0.1:3000, You can view the page that is returned.

Specific program reference: Web server download

TCP/IP protocol learning (iv) Web server---Static resource processing based on C # socket

Related Article

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.