上善若水
          In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
          posts - 146,comments - 147,trackbacks - 0

          概述

          Jetty作為HTTP服務(wù)器,服務(wù)器和客戶端以HTTP協(xié)議格式通信,Jetty使用Parser(HttpParser)來抽象HTTP請求消息和響應(yīng)消息的解析類引擎。在HttpParser實現(xiàn)中,它采用有限狀態(tài)機算法:定義了21中狀態(tài),每解析一個字符,就根據(jù)當前的狀態(tài)做相應(yīng)的處理,并決定是否要遷移到下一個狀態(tài),直到HTTP請求消息或響應(yīng)消息解析完成。HttpParser采用事件驅(qū)動機制,它定義了EventHandler類,用戶可以通過注冊的EventHandler實例獲取相應(yīng)的消息:請求行解析完成(startRequest)、響應(yīng)行解析完成(startResponse)、每個消息頭解析完成(parsedHeader)、所有消息頭解析完成(headerComplete)、消息內(nèi)容解析完成(content)、整個消息(請求消息或響應(yīng)消息)解析完成(messageComplete)。

          Parser接口定義

          public interface Parser {
              // 重置Parser的內(nèi)部狀態(tài),以重用Parser實例,如果returnBuffers為true,則將內(nèi)部Buffer回收。
              void reset(boolean returnBuffers);
              // 當前Parser是否已經(jīng)解析完成。
              boolean isComplete();
              // 當前Parser是否處于Idle狀態(tài),它還處于初始狀態(tài),解析還沒有開始。
              boolean isIdle();
              // 內(nèi)部Buffer是否還有內(nèi)容沒有解析。
              boolean isMoreInBuffer() throws IOException;
              // 開始解析已接收到的消息,返回-1表示解析到流的末位,0表示沒有該次調(diào)用沒有解析任何消息,>0表示這次調(diào)用總共解析過的字節(jié)數(shù)。
              int parseAvailable() throws IOException;
          }

          EventHandler定義

          public static abstract class EventHandler {
              // 消息內(nèi)容解析完成
              public abstract void content(Buffer ref) throws IOException;

              // 所有消息頭解析完成
              public void headerComplete() throws IOException {
              }

              // 整個消息(請求消息或響應(yīng)消息)解析完成
              public void messageComplete(long contentLength) throws IOException {
              }

              // 每個消息頭解析完成
              public void parsedHeader(Buffer name, Buffer value) throws IOException {
              }

              // 請求行解析完成
              public abstract void startRequest(Buffer method, Buffer url, Buffer version)
                      throws IOException;

              // 響應(yīng)行解析完成
              public abstract void startResponse(Buffer version, int status, Buffer reason)
                      throws IOException;
          }

          EventHandler的實現(xiàn)類

          在HttpConnection的內(nèi)部類RequestHandler類實現(xiàn)了HttpParser.EventHandler類,以作為HttpParser使用時的回調(diào)。
          startRequest:重置當前HttpConnection狀態(tài),HttpRequest的時間戳,設(shè)置新解析出來的RequestMethod、URI、version信息。
          parsedHeader:將每個HTTP頭(name, value)對添加到_requestFields字段中,并檢查某些頭的存在性以及其值的合法性。
          1. 如果“host”頭存在,則設(shè)置_host為true。
          2. 對“Expect”頭,如果其值是“100-continue”,設(shè)置_expect100Continue為true,若值是“102-processing”,設(shè)置_expect102Processing值為true,當信息不足時,設(shè)置_expect為true。
          3. 對“Accept-Encoding”和“User-Agent”頭,只能是預定義的值。
          4. 對“Content-Type”頭只能是預定義的值,并且根據(jù)該值設(shè)置_charset字段。
          5. 對“Connectin”頭,如果是“close”值,則設(shè)置HttpGenerator的persistent屬性為false,并且設(shè)置_responseFields的“Connection”值為“close”,否則為“keep-alive”。
          headerComplete:在HTTP消息頭解析結(jié)束后,對AsyncEndpoint,調(diào)用其scheduleIdle()方法,設(shè)置HttpGenerator中的HTTP version字段,以及當前請求是否為HEAD請求,如果當前Server配置了sendDateHeader,則設(shè)置HttpGenerator的Date字段為HttpRequest的時間戳(在startRequest方法調(diào)用是設(shè)置)。對HTTP/1.1,如果沒有設(shè)置Host頭,直接返回400響應(yīng)(調(diào)用_generator的completeHeader和complete方法);如果expect為true,表示Expect頭設(shè)置有問題,直接返回417響應(yīng)(調(diào)用_generator的completeHeader和complete方法)。設(shè)置_charset字段,對CHUNK請求立即開始處理請求(handleRequest),否則延遲到消息讀取完成。
          content:對AsyncEndPoint,調(diào)用其scheduleIdle()方法,如果請求還未開始處理,則立即開始處理請求。
          messageComplete:如果請求還未開始處理,則立即開始處理請求。

          注:這里并沒有在content方法中保存消息體的內(nèi)容,在Jetty中使用HttpInput類從HttpParser中直接讀取消息體的內(nèi)容(通過HttpInput的read方法調(diào)用HttpParser.blockForContent()方法)。

          HttpPaser有限狀態(tài)機實現(xiàn)

          在HttpParser中定義了21中狀態(tài),其中STATE_END以前的狀態(tài)用于解析HTTP頭消息,而STATE_END以后的狀態(tài)用于解析HTTP消息體。它們各自的狀態(tài)遷移圖如下。

          HttpParser在解析HTTP消息頭時的狀態(tài)遷移圖

          HttpParser在解析HTTP消息體時的狀態(tài)遷移圖

          HttpParser在HttpConnection類中的使用

          HttpParser在HttpConnection中的handle方法被調(diào)用時用于解析客戶端過來的HTTP請求消息。
          if (!_parser.isComplete()) {
               int parsed=_parser.parseAvailable();
               if (parsed>0)
                   progress=true;
          }
          posted on 2014-04-19 18:31 DLevin 閱讀(2513) 評論(3)  編輯  收藏 所屬分類: Jetty

          FeedBack:
          # re: 深入Jetty源碼之HttpParser
          2014-04-21 10:53 | 無添加
          想問下TF-IDF算法實現(xiàn)的具體事例有嗎?  回復  更多評論
            
          # re: 深入Jetty源碼之HttpParser
          2014-05-15 05:00 | jptan
          請問博主是如何把uml圖做出來的呢?  回復  更多評論
            
          # re: 深入Jetty源碼之HttpParser
          2014-05-15 13:54 | DLevin
          用StarUML@jptan
            回復  更多評論
            
          主站蜘蛛池模板: 海晏县| 五河县| 宜宾市| 大渡口区| 山东| 贵南县| 吉安县| 合川市| 阿克| 佛山市| 台南县| 南通市| 宾阳县| 枞阳县| 邹城市| 晋宁县| 苗栗市| 收藏| 来安县| 通榆县| 乳源| 正镶白旗| 西峡县| 永新县| 廊坊市| 东城区| 扎赉特旗| 京山县| 清徐县| 宾川县| 含山县| 万山特区| 湖北省| 吴旗县| 常州市| 湘乡市| 双城市| 灌阳县| 府谷县| 读书| 长岛县|