<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                lighttpd請求處理的過程: 1.服務器與客戶端建立連接后,連接進入CON_STATE_REQUEST_START狀態,服務器做一些標記,如連接開始的時間等。 2.連接進入CON_STATE_READ狀態,服務器從連接讀取HTTP頭并存放在con->requeset.request中。若一次調用沒能讀取全部數據,連接的狀態將繼續為READ,繼續等待剩下的數據可讀。 在對joblist進行處理的時候,依然會調用connecion_handle_read_state函數進行處理,函數中通過con->is_readable來判斷是否有數據可讀,如果沒有,則只是處理一下以前已經讀取的數據。 3.數據讀取完之后,連接進入CON_STATE_REQUEST_END狀態。 4.在REQUEST_END階段,調用http_request_parse函數解析request請求。 函數首先解析Request line,解析出來的結果存放在con->request.http_method, con->request.http_version和con->request.uri中(前兩個變量都是枚舉類型,后一個是個buffer)。 解析完request line后,開始分析header lines。找到一個header field name后,就和所有已經定義的field name比較,看看是哪個。確定之后,就將field name和value保存到con->request.headers中。request.headers是一個array類型變量,存放的是data_string類型數據。其中,data_string的key是filed name,value就是field的成員。 5.解析完之后判斷此次連接是否有POST數據,有則讀取POST數據,否則進入HANDLE_REQUEST狀態。 6.如果有POST數據要讀,連接進入READ_POST狀態。 READ_POST狀態的處理和READ狀態類似。 在connection_state_mechine函數中,這兩個switch分支一樣。在connection_handle_read_state函數中,前半部分讀取數據是一樣的,后面處理數據時才分開。 對于POST數據,由于數據可能很大,這時候可能會用到臨時文件來存儲。在程序中,作者對于小于64k的數據,直接存儲在buffer中,大于64k則存儲在臨時文件中。在向臨時文件寫數據時,每個臨時文件只寫1M的數據。數據大于1M就再打開一個臨時文件。 POST數據保存在con->requeset_content_queue,這是一個chunkqueue類型的成員變量,它是chunk結構體的鏈表: ~~~ typedef struct { chunk *first; chunk *last; /** * 這個unused的chunk是一個棧的形式。 * 這個指針指向棧頂,而chunk中的next指針則將棧連 接起來。 */ chunk *unused; size_t unused_chunks; array *tempdirs; off_t bytes_in, bytes_out; } chunkqueue; ~~~ unused成員是棧形式的鏈表,unused指向棧頂。它用來存儲不用的chunk結構體,如果需要chunk,則先從這個棧中查找有無空閑的。如果chunk不使用了,可以加到棧頂。這樣可以減少內存分配的時間,提高程序的效率。unused_chunks標記棧中有多少數據。 chunk的定義: ~~~ typedef struct chunk { enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type; /* 內存中的存儲塊或預讀緩存 */ buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */ struct { /* * filechunk 文件塊 */ buffer *name;/* name of the file */ off_t start;/* starting offset in the file */ off_t length;/* octets to send from the starting offset */ int fd; struct { char *start;/* the start pointer of the mmap'ed area */ size_t length;/* size of the mmap'ed area */ off_t offset; /* start is <n> octet away from the start of the file */ } mmap; int is_temp;/* file is temporary and will be deleted if on cleanup */ } file; off_t offset;/* octets sent from this chunk the size of the * chunk is either -mem-chunk: mem->used - 1 file-chunk: file.length */ struct chunk *next; } chunk; ~~~ chunk用來表述一塊存儲空間。這個存儲空間可能在內存中,也可能在文件中。 type成員標記這個塊是內存的還是文件的。 mem成員指向內存中的存儲空間(實際上是一個buffer)。 file結構體則表示在文件中的存儲空間(程序首先使用mmap函數將文件映射到內存中,mmap結構體的start成員保存映射到內存中的地址,于是對于文件的操作就可以像內存一樣)。 7.讀取完數據之后,進入HANDLE_REQUEST狀態,此時請求已經解析完畢,本狀態需要決定如何處理請求。 該狀態調用http_response_prepare函數,然后根據函數的返回值進行相應的處理(http_response_prepare函數定義在response.c文件中,函數中調用了很多plugins_call_handle_xxxx函數,插件系統的接口函數主要是在這個函數中調用,這個函數也是服務器和插件系統交互的地方)。 在http_response_prepare函數中,通過對url的解析,逐步的調用插件來處理。對url解析的結果存放在con->uri中: ~~~ typedef struct { buffer *scheme; //http , https and so on buffer *authority; //user:password buffer *path; //www.xxx.com/xxx/xxxx.html buffer *path_raw; //www.xxx.com buffer *query; //key1=data1&key2=data2 } request_uri; ~~~ uri的定義為:(scheme)://(authority)(path)?(query)#fragment。 如: [http://user:passwd@www.google.com/pages/index.html?key1=data1&key2=data2#frag](http://user:passwd@www.google.com/pages/index.html?key1=data1&key2=data2#frag) 解析之后: ~~~ scheme = http authority = user:passwd path = www.google.com/pages/index.html path_raw = 未進行解碼的path query = key1=data1&key2=date2 ~~~ 注意,在瀏覽器向服務器發送url請求的時候,會對其中的保留字符和不安全字符進行編碼(參見RFC2396),比如漢字。編碼的形式是% HEX HEX,即一個%加兩個十六進制數。服務器在接到請求之后,要對這些編碼過的字符進行解碼。path_raw中保存的是還沒解碼的url,path保存的是已解碼的url。 對fragment服務器直接拋棄,因為fragment是瀏覽器使用的。 當解析出url中的path之后,服務器調用插件的plugins_call_handle_uri_raw函數,插件根據未解碼的url path進行處理。 如果沒有插件進行處理,服務器調用插件的plugins_call_handle_uri_clean函數,它根據解碼過的url path進行處理。 在這里,服務器根據解析出來的url地址直接將請求轉發給插件,而不需要自己對請求進行處理。 當請求仍然沒有被處理時,說明這個請求必須要在這被處理。服務器調用插件的plugins_call_handle_docroot函數對處理請求時的根目錄進行設置。對于不同種類的資源,可以設置不同的根目錄,提供一個虛擬服務器。接著,服務器根據根目錄和請求的url地址,拼接出資源在本機上對應的物理地址。比如,doc root = /abc/root, url path = /doc/index.html,得到的物理地址就是/abc/root/doc/index.html。然后服務器調用插件的plugins_call_handle_physical函數,根據得到的物理地址進行相應的處理。最后,服務器調用插件的plugins_call_handle_subrequest_start函數和plugins_call_handle_subrequest函數進行最后的處理。 8.連接進入CON_STATE_RESPONSE_START狀態,服務器準備給客戶端的response,包括準備response頭和寫數據。 參考: [http://www.cnblogs.com/kernel_hcy/archive/2010/04/07/1706587.html](http://www.cnblogs.com/kernel_hcy/archive/2010/04/07/1706587.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看