Objective
After one months, and finally have time to update my server, this update is mainly to implement the CGI protocol.
First put on GitHub link tinyserver-github-Pillow Book
As a server, the basic requirement is to accept the request, extract the information and distribute the message to the CGI interpreter, and then wrap the message of the interpreter response back to the client. In this process, in addition to interacting with the client socket, it involves a third entity-the request interpreter.
The client is responsible for encapsulating the request and analyzing the response, the primary responsibility of the server is to manage the connection, data transformation, transmission and distribution of client requests, while the real data document processing and database operation is the request interpreter, this interpreter, in PHP is generally Php-fpm,java is Servlet.
Our previous handling of the communication between the client and the server, as well as the internal tuning of the server, the content of this update is mainly between the following two entities inter-process communication.
Inter-process communication involves three aspects, namely, 方式
and 形式
and 内容
.
The way refers to the process of communication between the transmission medium, such as Nginx implementation of the TCP and Unix Domain sockets, they have the advantages of cross-machine and high efficiency, and I implement the server in a very low popen
way.
And form is the data format, I think it does not have the formula, as long as the server easy to organize data, the interpreter can easily receive and parse, it is best to save the transmission of resources, improve transmission efficiency. The current solution has classic XML, lightweight and easy to understand JSON and Google's efficient protobuf. They have advantages, I chose the JSON, mainly because of the existence of the Cjson library, the data in C Chinese organization, and in PHP, a json_decode()
method to complete the data analysis.
What should be transmitted? CGI describes a set of protocols:
Cgi
The Universal Gateway Interface (Common Gateway interface/cgi) is an important Internet technology that allows a client to request data from a Web browser to a program that executes on a network server. CGI describes a standard for transferring data between a server and a request handler.
CGI is the interface between the server and the interpreter, the server is responsible for accepting requests and interpreting the request information as a basic set of request information (called "Metadata" in the document), which is passed to the interpreter to interpret the execution, while the interpreter responds to the document and the database operation information.
Before looking at the CGI RFC document, summed up a few important points, interested can look at the bottom of the reference document. Common specifications (too much information, only consider must) are as follows:
CGI Request
/
the server chooses the interpreter based on a delimited path;
- If there is a
AUTH
field, you need to execute the AUTH before executing the interpreter;
- The server acknowledgment indicates the length of the
CONTENT-LENGTH
data parsing, and if it comes with an information body, the length field must be passed to the interpreter;
- If there is a
CONTENT-TYPE
field, the server must pass it to the interpreter, and if there is no such field, but there is an information body, the server determines the type or discards the information body;
- The server must set the
QUERY_STRING
field, if the client is not set, the service side to pass an empty string ""
- The server must be set
REMOTE_ADDR
, that is, the client request IP;
REQUEST_METHOD
Fields must be set, GET POST, etc., case sensitive;
SCRIPT_NAME
Represents the execution of the interpreter script name, which must be set;
SERVER_NAME
and a SERVER_PORT
TCP/IP port representing the case-sensitive server name and server acceptance;
SERVER_PROTOCOL
field indicates the type of protocol that the server negotiates with the interpreter, not necessarily the same schema as the client request, such as ' https://' may be http;
- In the
CONTENT-LENGTH
case of non-null, the server to provide the information body, the information body to be strictly consistent with the length, even if there is more readable information can not be more than pass;
- The server must parse data compression and other encoding;
CGI response
- The CGI interpreter must respond to at least one line header + line break + response content;
- The interpreter must have a head in response to the document
CONTENT-TYPE
;
- In addition to the client redirection, the interpreter
client-redir-response=绝对url地址
can no longer return, and the server returns a 302
status code;
- The interpreter responds to the three-bit digital status code, which can be searched by itself;
- The server must respond to the client with all the data returned by the interpreter, and the server cannot modify the response data unless encoding is required;
The CGI implementation of Nginx and PHP
After the introduction of CGI, let's refer to the current server CGI protocol implementation of the mature solution, here to choose my familiar Nginx and PHP.
In the combination of Nginx and PHP, Nginx is a natural server, and the interpreter is PHP SAPI.
SAPI
The Sapi:server abstraction API, which refers to the programming interface for specific PHP applications, allows PHP to interact with other applications.
PHP scripts can be executed in many ways through a WEB server, either directly under the command line or embedded in other programs. The common SAPI is apache2handler、fpm-fcgi、cli、cgi-fcgi
that the PHP function can be php_sapi_name()
used to view the SAPI that the current PHP execution uses.
PHP5.3 previously used to interact with the server SAPI is cgi
that it implements the basic CGI protocol, because it each processing request to create a process, initialization process, processing requests, destroy process, consumption is too large, so that the system performance greatly reduced.
The upgrade version of the CGI protocol fast-cgi.
php-fpm
Fast Universal Gateway Interface (Fast Common gateway interface/fastcgi) is a protocol that enables interactive programs to communicate with a Web server. FASTCGI is an enhanced version of the early Universal Gateway Interface (CGI).
The fast-cgi efficiency mainly relies on the long-standing memory of the CGI interpreter, which avoids the loss of the process loading repeatedly. PHP's SAPI cgi-fcgi
implements the FAST-CGI protocol, which improves the efficiency of PHP's processing of WEB requests.
So what are our common php-fpm? It is a process manager, php-fastcgi process Manager, that manages the processes that implement fast-cgi (worker processes), loads php.ini
information, initializes worker processes, and implements smooth restarts and other advanced features.
Nginx will give the request to PHP-FPM,FPM select an idle worker process to process the request.
Rectification
Here is a summary of several names to avoid confusion:
- SAPI, which is the interface between PHP and the external process;
- CGI/FAST-CGI (uppercase) is a protocol;
- The CGI (lowercase) that appears in this section refers to PHP's SAPI, an interface that implements the CGI protocol.
- PHP-FPM is
实现了Fast-CGI协议的进程
a process of management.
Code implementation
Introduced the high-end Nginx server, say my implementation:
The server parses the HTTP message, implements the CGI protocol, wraps the data in JSON format, cli
sends it to the PHP process via PHP's SAPI, and responds to JSON-formatted data after parsing the PHP process, and the server parses the response data and wraps it into an HTTP response message sent to the client.
Http_parser
The first task is to parse the HTTP message, C is not rich in string functions, I have not encapsulated the usual library of functions, so I have to temporarily implement a util_http.c
, here are a few processing HTTP messages useful string function.
strtok(char str[], const *delimeter)
, the Delimeter is set to "\n"
the branch processing HTTP headers just right.
sscanf(const *str, format, dest1[,dest...])
, which reads a string from a string in a specific format, and the delimiter to read is a space, which is handy for handling HTTP request lines.
As for parsing the HTTP header of the key value corresponding, did not think of a good method, had to use character traversal to judge.
Cjson
Cjson is a C-implemented library of functions for generating and parsing JSON-formatted data that can be easily found on GitHub, with only two files cJSON.c
and one cJSON.h
.
Note: C, as a strongly typed language, adds different types of data to the JSON using different methods, Cjson support string, bool, number, cJSON object
, and so on.
Here is a brief introduction to the general method of generating and parsing;
Generated:
cJSON *root; // 声明cJSON格式数据root = cJSON_CreateObject(); // 创建一个cJSON对象cJSON_AddStringToObject(root, "key", "value") // 往cJSON对象内添加键值对char *output = cJSON_PrintUnformatted(root); // 生成json字符串cJSON_Delete(root); // 别忘记释放内存
Analytical:
cJSON *json = cJSON_Parse(response_json);value = cJSON_GetObjectItem(cJSON, "key");
Of course, you can also declare Cjson types of data to be nested;
Summarize
To tell the truth, using the most basic C write business logic Class code really can torture the dead, only a string of operations can make people want to die. Common C development should have a variety of function library bar, even if you do not have their own library to find the Open source Library, you can not build all the wheels.
Feel the server has been written by themselves, left a lot of business types of pits do not know when will fill, hope to have time to write an industrial-grade things ...
If you feel that this article is helpful to you, you can click on the recommendation below to support me. Blog has been updated, welcome attention .
Reference: The Common Gateway Interface (CGI) Version 1.1
Deep understanding of the PHP kernel? Life cycle and Zend engine
I can't figure out what kind of relationship fastcgi and PHP-FPM are.
Write a Web server (quad) CGI protocol in C