<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                在CON_STATE_RESPONSE_START狀態中,服務器開始準備給客戶端的response: ~~~ case CON_STATE_RESPONSE_START: /* * the decision is done * - create the HTTP-Response-Header * */ if (srv->srvconf.log_state_handling) { log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } if (-1 == connection_handle_write_prepare(srv, con)) { connection_set_state(srv, con, CON_STATE_ERROR); break; } connection_set_state(srv, con, CON_STATE_WRITE); break; ~~~ 可以看到,該狀態主要調用了connection_handle_write_prepare函數,它根據客戶端請求的method來設置response的headers(其實就是設置“Content-Length”的值)。 connection_handle_write_prepare函數的執行內容: 1.該函數首先判斷連接的模式(mode)是否為DIRECT,如果是,說明連接沒有經過插件處理,是由服務器自身處理的。 2.接著判斷連接的請求method,如果是OPTION,則設置Allow的值,同時清空write_queue,因為沒有數據需要返回。設置con->file_finished為1,表示不需要給客戶端發送文件。 3.比較http_status的值,如果為204,205,304,說明服務器不需要給客戶端返回文件,僅返回 response中headers及其之前的部分,設置con->file_finished為1。 4.判斷file_finished的值。如果值為1,說明不需要給客戶端返回文件數據。對于1xx,204和 304狀態,將Content-Length設置為空值。如果method是HEAD,那么服務器可能需要返回一些數據,這時候要設置對應的 Content-Length。如果file_finished的值為0,那么要設置一下keep_alive的值。 5.最后,調用http_response_write_header將 headers寫入write_queue,等待返回給客戶端。如果一切順利,狀態機進入CON_STATE_WRITE狀態。 下面是CON_STATE_WRITE分支的操作: ~~~ case CON_STATE_WRITE: if (srv->srvconf.log_state_handling) { log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } /* only try to write if we have something in the queue */ if (!chunkqueue_is_empty(con->write_queue)) { #if 0 log_error_write(srv, __FILE__, __LINE__, "dsd", con->fd, "packets to write:", con->write_queue->used); #endif } if (!chunkqueue_is_empty(con->write_queue) && con->is_writable) { if (-1 == connection_handle_write(srv, con)) { log_error_write(srv, __FILE__, __LINE__, "ds", con->fd, "handle write failed."); connection_set_state(srv, con, CON_STATE_ERROR); } else if (con->state == CON_STATE_WRITE) { con->write_request_ts = srv->cur_ts; } } break; ~~~ 由于數據可能不會一次寫完,所以在CON_STATE_WRITE狀態中,首先判斷write_queue是否為空,即有沒有數據需要發送。同時判斷連接是否可寫。如果有數據且可寫,那么調用connection_handle_write發送數據。如果沒有數據可寫或者連接不可寫,那么跳出switch(con->state)這個語句。 由于狀態機狀態沒有發生改變,switch后面的if語句使得服務器退出了大while循環,進入循環后面的小switch(con->state)語句(如果連接的狀態沒有改變,說明連接讀寫數據還沒有結束,但是需要等待IO事件)。在這里,進入 CON_STATE_WRITE分支,如果有數據可寫且連接可寫且沒有達到流量限制,那么在fdevent中注冊這個連接,等IO結束后繼續寫數據,否則,刪除這個連接。 當有數據可寫且連接可寫時,進入connection_handle_write函數,下面看看該函數的作用: 1.首先調用network_write_chunkqueue函數,將write_queue中的數據寫回給客戶端。函數network_write_chunkqueue首先判斷當前連接的流量是否超過了限制,如果是,則不發送任何數據,直接將連接加到作業列表(joblist)中,讓其他連接發送數據。如果沒有超限,那么首先設置TCP_CORK選項。這個選項可以將多個write調用的數據一起發送, 提高發送效率。 2.接下來調用srv->network_backend_wirte()函數真正的寫數據。這個函數的定義有多個,在network_*.c文件中。服務器在network.c的network_init函數中會根據當前的運行環境設置不同的值。傳統的IO方法先read再write,需要4次數據拷貝(從磁盤到內核緩沖區,從內核緩沖區到用戶緩沖區,從用戶緩沖區到網絡接口的內核緩沖區,最后,從網絡接口的內核緩沖區到網絡設備緩沖區),為提高服務器的效率,不同的OS會提供一些特定的方法來減少拷貝的次數(直接IO),提高發送文件的速度,lighttpd根據不同的OS去調用特定的接口來實現network_backend_wirte()函數。這些實現大同小異,以network_write.c中的實現為例: 函數的主體是個大循環,遍歷所有的chunk。 如果chunk的類型是 MEM_CHUNK,那么這個chunk中的數據是在內存中的,直接調用write或者windows下的send函數發送數據。 如果是 FILE_CHUNK類型,說明這個chunk表示的是一個文件,那么如果運行環境有mmap函數,就使用mmap映射文件并發送,否則就read再write。 如果這個chunk發送完了,則繼續發送下一個chunk。 如果沒有發送完(chunk_finished=0),退出循環,接著退出了這個函數。 3.服務器返回到network_write_chunkqueue中,做一些統計工作,再一次檢查該連接的流量是否超限。 4.最后服務器返回到connection_handle_write中。 如果network_write_chunkqueue返回-1,表示服務器出錯。狀態機進 入CON_STATE_ERROR。 如果返回-2,則客戶端關閉連接,狀態機也進入CON_STATE_ERROR。 返回0表示發送完畢,進入下一個狀態。 返回1說明數據沒有發送完,標記is_wirtable為0。 5.從connection_handler_write函數返回后,如果數據沒有發送完畢,那么狀態機還在CON_STATE_WRITE狀態,接著連接被加到fdevent系統中,等待下一次數據發送。重復上述過程直到發送完畢或出錯。 6.如果數據發送完畢,狀態機進入CON_STATE_RESPONSE_END狀態。 在狀態CON_STATE_RESPONSE_END中: 1.服務器首先調用 plugins_call_handle_request_done通知所有插件連接處理完畢。 2.判斷是否保持連接,如果保持,將狀態機設置為 CON_STATE_REQUEST_START。如果不保持,先調用plugins_call_handle_connection_close通知所有插件連接關閉,然后關閉連接。 3.重置con,清除前一次請求的數據。    至此,請求處理結束。
                  <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>

                              哎呀哎呀视频在线观看