<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 功能強大 支持多語言、二開方便! 廣告
                在[從輸入網址到瀏覽器返回內容(一),服務器處理篇](http://www.cnblogs.com/dy2903/p/8305881.html "從輸入網址到瀏覽器返回內容(一),服務器處理篇")提到了Web服務器以及應用服務器,它主要用來接收從瀏覽器發過來的HTTP請求,并進行頁面的呈現。 本文主要講一下HTTP服務器的進化過程 # HTTP服務器1.0:單進程 所謂`HTTP協議`實際上就是瀏覽器向服務器發送一個HTTP Request請求,然后HTTP服務器進行處理,從硬盤拿一個HTML文件,然后以文本的形式返回過去(HTTP response) 麻煩的是需要請操作系統建立HTTP協議下面的TCP連接通道。這個通道是通過Socket建立的: - 先在80端口監聽 - 進入無限循環,如果有連接請求來,就接受(accept) - 創建新的socket,然后通過這個新的socket來接收,發送HTTP數據 這就是HTTP Server 1.0版本。 但是網絡傳輸是不穩定的,有可能很長時間都沒有響應,所以服務器的receive進程很可能因為得不到數據而**阻塞**。但是進程也不能歇著,因為還有很多瀏覽器的連接在那里等著。 解決方案就是為每個請求開一個進程或者線程 # HTTP服務器2.0:多進程 多進程的思路是當accept獲得到連接的時候,生成了新的socket,但是不在主進程里面處理,而是**新創建一個子進程**來接管。這樣主進程就不會阻塞在receive上,可以繼續接受新的連接了。 但是如果有成千上萬個連接來了以后,如果每個連接都開一個進程,而每個進程都**耗費大量的系統資源,而且進程切換也非常消耗資源。** 如果把多進程換為多線程,只能說可能會好一點,但是治標不治本。 ![](http://p8a6vmhkm.bkt.clouddn.com/img/20181029141615.png?imageslim) # HTTP 服務器3.0:Select模型 之前的方法存在一個非常大的問題,一個Socket連接就是一個文件描述符,這個描述符是個指針指向一個簡單的數據結構,但是我們用了一個重量級的進程來對它進行讀寫,非常的浪費。 那么思路又回到了單進程上,只需要**改變一下工作方式**就可以用單進程進行連接的處理。 在1.0的階段,為什么會阻塞,因為瀏覽器只是和我們建立了連接,但是沒有把**數據**發送過來,但是我們又迫不及待的去讀,所以只能阻塞。所以,問題的癥結就在于此。 所以,可以接收了客戶端連接以后,**不急著讀**,而是拿到socket fd的編號,就可以處理其他的連接了。 下面操作系統會在后臺檢查socket,如果發現有socket可以讀寫了,就會做個**標記**,然后通知HTTP服務器。 HTTP服務器遍歷一遍所有的socket 描述符,看看誰有標記,有標記的才做處理。 處理完了,把socket的描述符告訴操作系統,然后再繼續等待, 這種方式就是Select ![](http://p8a6vmhkm.bkt.clouddn.com/img/20181029141628.png?imageslim) # HTTP服務器4.0:epoll Select方法存在一個弊端,每次被喚醒之后,需要遍歷所有的socket 描述符,看看是否有標志位。 所以要如果能把**發生了變化的socket**告訴HTTP服務器就好了。這種方式就是epoll。 使用了epoll,就不需要遍歷全部的集合,只需要處理哪些有變化的。 ![](http://p8a6vmhkm.bkt.clouddn.com/img/20181029141637.png?imageslim) # 參考 [Http Server:一個差生的逆襲](http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513467&idx=1&sn=178459f4bb9891c9cf471a28e7c340be&chksm=80d679b8b7a1f0aea8f6e3f09acb6969993825753170dc3db63f8ef35c95cce98aa40a0c7097&scene=21#wechat_redirect)
                  <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>

                              哎呀哎呀视频在线观看