日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

tomcat(4)Tomcat的默认连接器

發布時間:2023/12/3 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 tomcat(4)Tomcat的默认连接器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【0】README 0.0)本文部分文字描述轉自:“深入剖析tomcat”,旨在學習?tomat(4)Tomat的默認連接器 的基礎知識; 0.1)Tomcat中的連接器是一個獨立的模塊,可以插入到servlet容器中,而且還有很多連接器可以使用; 0.2)Tomcat中使用的連接器必須滿足如下要求(requirement): r1)實現 org.apache.catalina.Connector 接口; r2)負責創建實現了 org.apache.catalina.Request接口的request對象; r3)負責創建實現了 org.apache.catalina.Response接口的response對象; 0.3)連接器會等待HTTP請求,以創建request 和 response對象,然后調用 org.apache.catalina.Container接口的 invoke方法,將request對象和response對象傳給 servlet容器。invoke() 方法簽名如下:(干貨——這里涉及到類加載器) public void invoke(Request request, Response response) // SimpleContainer.invokethrows IOException, ServletException {String servletName = ( (HttpServletRequest) request).getRequestURI();servletName = servletName.substring(servletName.lastIndexOf("/") + 1);URLClassLoader loader = null;try { // 創建類加載器URL[] urls = new URL[1];URLStreamHandler streamHandler = null;File classPath = new File(WEB_ROOT);String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;urls[0] = new URL(null, repository, streamHandler);loader = new URLClassLoader(urls);}catch (IOException e) {System.out.println(e.toString() );}Class myClass = null;try {myClass = loader.loadClass("servlet." + servletName);}catch (ClassNotFoundException e) {System.out.println(e.toString());}Servlet servlet = null;try {servlet = (Servlet) myClass.newInstance(); // 創建請求URI對應的servlet實例 servlet.service((HttpServletRequest) request, (HttpServletResponse) response);}......} 0.3.1)invoke方法內部:servlet容器會載入相應的servlet類,調用其 service() 方法,管理session對象,記錄錯誤消息等操作; 0.3.2)Tomcat4的默認連接器使用了一些優化方法:一、使用了一個對象池來避免了頻繁創建對象帶來的性能損耗;二、在很多地方,Tomcat4 的默認連接器使用了字符數組來代替字符串;(干貨——Tomcat4的默認連接器使用了一些優化方法 0.4)for complete source code, please visit?https://github.com/pacosonTang/HowTomcatWorks/tree/master/chapter4; 0.5)本文講解的是 tomcat中的默認連接器,而 這篇博文?tomcat(3)連接器?講解的是以前的前輩自定義的連接器(功能和tomcat默認連接器類似),這旨在學習 tomcat中默認連機器的原理。 0.6)溫馨建議:建議閱讀本文之前,已閱讀過 tomcat(1~3)的系列文章,因為它們是環環相扣的;

【1】HTTP 1.1 的新特性 【1.1】持久連接 1)intro to persistent connect:在HTTP1.1之前, 無論瀏覽器何時連接到web server,當server返回請求資源后,會斷開與瀏覽器的連接,但網頁上會包含一些其他資源,如圖片;所以,當請求一個頁面時,瀏覽器還需要下載這些被頁面引用的資源。如果頁面和它引用的所有資源文件都使用不同的連接進行下載的話,處理過程會很慢;這也就是為什么會引入持久連接;(干貨——引入持久連接的原因) 1.1)使用持久連接后,當下載了頁面后,server并不會立即關閉連接,相反,它會等待web client請求被該頁面引用的所有資源。這樣一來,頁面和被引用的資源都會使用同一個連接來下載。考慮到建立/關閉 HTTP 連接是一個系統開銷很大的操作,使用同一個連接來下載所有的資源會為web server, client 和 網絡節省很多時間和工作量; 1.2)如何默認使用持久連接:瀏覽器發送如下的請求頭信息: connection: keep-alive
【1.2】塊編碼 1)建立持久連接后,server 可以從多個資源發送字節流,而客戶端也可以使用該連接發送多個請求。這樣的結果就是發送方必須在每個請求或響應中添加 content-length 頭信息。這樣,接收方才知道如何解釋這些字節信息。但發送方通常不知道要發送多少字節,所以必須有一種方法來告訴接收方在不知道發送內容長度的case下,如何解析已經接受到的內容; 2)HTTP1.1 使用一個名為 "transfer-encoding" 的特殊請求頭,來指明字節流將會分塊發送。對每一個塊,塊的長度(以16進制表示)后面會有一個回車/換行符(CR/LF),然后是具體的數據;一個事務以一個長度為0的塊標記。 2.1)看個荔枝:若要用兩個塊發送下面38個字節的內容,其中一塊為29個字節,第2個塊為9個字節:(干貨——塊編碼的一個荔枝) I'm as helpless as a kitten up a tree. 那么實際上應該發送如下內容: 1D\r\n I'm as helpless as a kitten u 9\r\n p a tree. 0\r\n 1D 的10進制表示是29, 表明第一個塊的長度是29個字節,\0\r\n 表明事務已經完成; 【1.3】狀態碼100的使用? 1)使用HTTP1.1的client 可以在向server發送請求體之前發送如下的請求頭,并等待server的確認: Expect: 100-continue //客戶端發送 2)server接收到 “Expect: 100-continue”請求頭后,若它可以接收并處理該請求時,發送如下響應頭: HTTP/1.1 100 continue //注意,返回內容后面要加上 CRLF 字符。然后server 繼續讀取輸入流的內容。
【2】Connector接口(Tomcat的連接器必須實現的接口) 1)該接口中聲明了很多方法,最重要的是 getContainer(), setContainer(), createRequest(), createResponse() 方法;
【3】HttpConnector類(實現了Connector, Runnable, Lifecycle 接口) public final class HttpConnectorimplements Connector, Lifecycle, Runnable { 1)Lifecycle接口:用于維護每個實現了 該接口的每個Catalina組件的生命周期; 2)HttpConnector實現了Lifecycle接口:因此當創建一個 HttpConnector實例后,就應該調用其initialize方法和start方法,在組件的整個生命周期內,這兩個方法只應該被調用一次; public final class Bootstrap {public static void main(String[] args) {HttpConnector connector = new HttpConnector();SimpleContainer container = new SimpleContainer();connector.setContainer(container);try {connector.initialize();connector.start();// make the application wait until we press any key.System.in.read();}catch (Exception e) {e.printStackTrace();}} } 【3.1】創建服務器套接字 1)HttpConnector類的 initialize方法:會調用一個私有方法open(),后者返回一個java.net.ServerSocket實例,賦值給成員變量serverSocket,它是通過open方法從一個服務器套接字工廠得到這個實例; public void initialize() // <span style="font-family: 宋體; font-size: 16px; line-height: 24px;"><strong>HttpConnector.initialize()</strong></span>throws LifecycleException {if (initialized)throw new LifecycleException (sm.getString("httpConnector.alreadyInitialized"));this.initialized=true;Exception eRethrow = null;// Establish a server socket on the specified porttry {serverSocket = open();} catch (IOException ioe) {log("httpConnector, io problem: ", ioe);eRethrow = ioe;} catch (KeyStoreException kse) {log("httpConnector, keystore problem: ", kse);eRethrow = kse;} catch (NoSuchAlgorithmException nsae) {log("httpConnector, keystore algorithm problem: ", nsae);eRethrow = nsae;} catch (CertificateException ce) {log("httpConnector, certificate problem: ", ce);eRethrow = ce;} catch (UnrecoverableKeyException uke) {log("httpConnector, unrecoverable key: ", uke);eRethrow = uke;} catch (KeyManagementException kme) {log("httpConnector, key management problem: ", kme);eRethrow = kme;}if ( eRethrow != null )throw new LifecycleException(threadName + ".open", eRethrow);} private ServerSocket open() // HttpConnector.open()throws IOException, KeyStoreException, NoSuchAlgorithmException,CertificateException, UnrecoverableKeyException,KeyManagementException{// Acquire the server socket factory for this ConnectorServerSocketFactory factory = getFactory();// If no address is specified, open a connection on all addressesif (address == null) {log(sm.getString("httpConnector.allAddresses"));try {return (factory.createSocket(port, acceptCount));} catch (BindException be) {throw new BindException(be.getMessage() + ":" + port);}}// Open a server socket on the specified addresstry {InetAddress is = InetAddress.getByName(address);log(sm.getString("httpConnector.anAddress", address));try {return (factory.createSocket(port, acceptCount, is));} catch (BindException be) {throw new BindException(be.getMessage() + ":" + address +":" + port);}} catch (Exception e) {log(sm.getString("httpConnector.noAddress", address));try {return (factory.createSocket(port, acceptCount));} catch (BindException be) {throw new BindException(be.getMessage() + ":" + port);}}} 【3.2】維護 HttpProcessor 實例 1)在Tomcat默認的連接器中:HttpProcessor實例有一個HttpProcessor 對象池,每個HttpProcessor 實例都運行在其自己的線程中。這樣,HttpConnector實例就可以同時處理多個 HTTP請求了;(干貨——HttpProcessor 對象池就是一個Stack,并不是Vector private Stack processors = new Stack(); // HttpConnector.java void recycle(HttpProcessor processor) { // HttpConnector.java// if (debug >= 2)// log("recycle: Recycling processor " + processor);processors.push(processor);}private HttpProcessor createProcessor() {synchronized (processors) {if (processors.size() > 0) {// if (debug >= 2)// log("createProcessor: Reusing existing processor");return ((HttpProcessor) processors.pop()); // attend for this line.}if ((maxProcessors > 0) && (curProcessors < maxProcessors)) {// if (debug >= 2)// log("createProcessor: Creating new processor");return (newProcessor());} else {if (maxProcessors < 0) {// if (debug >= 2)// log("createProcessor: Creating new processor");return (newProcessor());} else {// if (debug >= 2)// log("createProcessor: Cannot create new processor");return (null);}}}}
補充 Collection體系 |--:List元素是有序的,元素可以重復,因為該集合體系有索引 ? ? |--:ArrayList:底層的數據結構使用的是數組結構,特點:查詢速度很快,但是增刪稍慢,線程不同步 ? ? |--:LinkedList:底層使用的是鏈表數據結構,特點:增刪速度很快,查詢稍慢 ? ? |--:Vector:底層是數組數據結構,線程同步,被ArrayList替代了 |--:Set ?元素是無序的,元素不可以重復 為什么要用 ArrayList 取代 Vector呢??因為, Vector 類的所有方法都是同步的(可以由兩個線程安全的訪問一個 Vector對象);但是, 如果由一個線程訪問 Vector, 代碼需要在同步操作上 耗費大量的時間;(干貨——ArrayList非同步訪問,而Vector同步訪問);而ArryaList 不是同步 的, 所以, 建議在不需要同步時 使用 ArrayList, 而不要使用 Vector; 補充over
2)在HttpConnector中:創建的HttpProcessor 實例的個數由兩個變量決定:minProcessors 和 maxProcessors; 2.1)初始,HttpConnector對象會依據minProcessors的數值來創建?HttpProcessor實例:若是請求的數目超過了HttpProcessor 實例所能處理的范圍,HttpConnector 實例就會創建更多的HttpProcessor實例,直到數目達到 ?maxProcessors 限定的范圍; 2.2)若希望可以持續地創建 HttpProcessor實例: 就可以將?maxProcessors 設定為負值; 2.3)看個代碼:下面的代碼是在 HttpConnector 類中的start方法中創建初始數量的 HTTPProcessor實例的部分實現:(干貨——HttpConnector.start方法調用了HttpConnector.newProcessor方法,而HttpConnector.newProcessor方法調用了HttpProcessor.start方法) public void start() throws LifecycleException { // HttpConnector.start()// Validate and update our current stateif (started)throw new LifecycleException(sm.getString("httpConnector.alreadyStarted"));threadName = "HttpConnector[" + port + "]";lifecycle.fireLifecycleEvent(START_EVENT, null);started = true;// Start our background threadthreadStart(); // invoke run method.// Create the specified minimum number of processorswhile (curProcessors < minProcessors) {if ((maxProcessors > 0) && (curProcessors >= maxProcessors))break;HttpProcessor processor = newProcessor();recycle(processor);}} private HttpProcessor newProcessor() { // H<span style="font-family: 宋體;">ttpConnector.newProcessor()</span>// if (debug >= 2)// log("newProcessor: Creating new processor");HttpProcessor processor = new HttpProcessor(this, curProcessors++);if (processor instanceof Lifecycle) {try {((Lifecycle) processor).start();} catch (LifecycleException e) {log("newProcessor", e);return (null);}}created.addElement(processor); // created is a Vector Collection.return (processor);} private Vector created = new Vector(); void recycle(HttpProcessor processor) { // HttpContainer.recycle()// if (debug >= 2)// log("recycle: Recycling processor " + processor);processors.push(processor);} public void stop() throws LifecycleException {// Validate and update our current stateif (!started)throw new LifecycleException(sm.getString("httpConnector.notStarted"));lifecycle.fireLifecycleEvent(STOP_EVENT, null);started = false;// Gracefully shut down all processors we have createdfor (int i = created.size() - 1; i >= 0; i--) {HttpProcessor processor = (HttpProcessor) created.elementAt(i); // this line.if (processor instanceof Lifecycle) {try {((Lifecycle) processor).stop();} catch (LifecycleException e) {log("HttpConnector.stop", e);}}}synchronized (threadSync) {// Close the server socket we were usingif (serverSocket != null) {try {serverSocket.close();} catch (IOException e) {;}}// Stop our background threadthreadStop();}serverSocket = null;} Attention) A0)顯然變量created是private類型:其在HttpConnector.java 中出現了3次,一次是?private Vector created = new Vector();, 一次是created.addElement(processor);還有一次是stop方法中(上述最后一段代碼)(干貨——但,HttpProcessor的對象池不是Vector而是Stack) A1)其中,newProcessor方法負責創建 HttpProcessor 實例,并將 curProcessors 加1;recycle() 方法將創建的HttpProcessor 對象入棧; A2)每個 HttpProcessor 實例負責解析HTTP請求行和請求頭, 填充 request對象; void recycle(HttpProcessor processor) { // // if (debug >= 2)// log("recycle: Recycling processor " + processor);processors.push(processor); // <span style="font-weight: bold; font-family: 宋體;">processors is a stack.</span>} private Stack processors = new Stack(); // HttpConnector.java 【3.3】提供HTTP請求服務 1)HttpConnector類的主要業務邏輯在其run() 方法中。run() 方法包含一個 while循環,在該循環體內,服務器套接字等待 HTTP請求,直到HttpConnector對象關閉; public void run() { // HttpConnector.run()// Loop until we receive a shutdown commandwhile (!stopped) {// Accept the next incoming connection from the server socketSocket socket = null;try {// if (debug >= 3)// log("run: Waiting on serverSocket.accept()");socket = serverSocket.accept();// if (debug >= 3)// log("run: Returned from serverSocket.accept()");if (connectionTimeout > 0)socket.setSoTimeout(connectionTimeout);socket.setTcpNoDelay(tcpNoDelay);} catch (AccessControlException ace) {log("socket accept security exception", ace);continue;} catch (IOException e) {// if (debug >= 3)// log("run: Accept returned IOException", e);try {// If reopening fails, exitsynchronized (threadSync) {if (started && !stopped)log("accept error: ", e);if (!stopped) {// if (debug >= 3)// log("run: Closing server socket");serverSocket.close();// if (debug >= 3)// log("run: Reopening server socket");serverSocket = open();}}// if (debug >= 3)// log("run: IOException processing completed");} catch (IOException ioe) {log("socket reopen, io problem: ", ioe);break;} catch (KeyStoreException kse) {log("socket reopen, keystore problem: ", kse);break;} catch (NoSuchAlgorithmException nsae) {log("socket reopen, keystore algorithm problem: ", nsae);break;} catch (CertificateException ce) {log("socket reopen, certificate problem: ", ce);break;} catch (UnrecoverableKeyException uke) {log("socket reopen, unrecoverable key: ", uke);break;} catch (KeyManagementException kme) {log("socket reopen, key management problem: ", kme);break;}continue;}// Hand this socket off to an appropriate processorHttpProcessor processor = createProcessor();if (processor == null) {try {log(sm.getString("httpConnector.noProcessor"));socket.close();} catch (IOException e) {;}continue;}// if (debug >= 3)// log("run: Assigning socket to processor " + processor);processor.assign(socket);// The processor will recycle itself when it finishes}// Notify the threadStop() method that we have shut ourselves down// if (debug >= 3)// log("run: Notifying threadStop() that we have shut down");synchronized (threadSync) {threadSync.notifyAll();}} 2)對于每個引入的HTTP請求,它通過 調用其私有方法 createProcessor() 獲得一個HttpProcessor對象; HttpProcessor processor = createProcessor(); // invoked by HttpContainer.run() method. private Stack processors = new Stack(); // you should know the processors is a Stack. private HttpProcessor createProcessor() { // HttpConnector.createProcessor() synchronized (processors) {if (processors.size() > 0) {// if (debug >= 2)// log("createProcessor: Reusing existing processor");return ((HttpProcessor) processors.pop());}if ((maxProcessors > 0) && (curProcessors < maxProcessors)) {// if (debug >= 2)// log("createProcessor: Creating new processor");return (newProcessor());} else {if (maxProcessors < 0) {// if (debug >= 2)// log("createProcessor: Creating new processor");return (newProcessor());} else {// if (debug >= 2)// log("createProcessor: Cannot create new processor");return (null);}}}}<span style="font-family: 宋體;"> </span>
3)若createProcessor() 方法的返回值不是null,則會將客戶端套接字傳入到 HttpProcessor類的 assign()方法中: // Hand this socket off to an appropriate processorHttpProcessor processor = createProcessor(); // these code are located in HttpConnector.run() if (processor == null) {try {log(sm.getString("httpConnector.noProcessor"));socket.close();} catch (IOException e) {;}continue;}// if (debug >= 3)// log("run: Assigning socket to processor " + processor);processor.assign(socket); // this line, invoked by HttpConnector.run method.// The processor will recycle itself when it finishes}// Notify the threadStop() method that we have shut ourselves down// if (debug >= 3)// log("run: Notifying threadStop() that we have shut down");synchronized (threadSync) {threadSync.notifyAll();} synchronized void assign(Socket socket) {// Wait for the Processor to get the previous Socketwhile (available) {try {wait();} catch (InterruptedException e) {}}// Store the newly available Socket and notify our threadthis.socket = socket;available = true;notifyAll();if ((debug >= 1) && (socket != null))log(" An incoming request is being assigned");} 4)現在,HttpProcessor實例的任務是讀取套接字的輸入流,解析HTTP請求。這里需要注意的是,assign方法直接返回,而不需要等待?HttpProcessor 實例完成解析,這樣 HttpContainer才能持續服務傳入的 HTTP請求,而 HttpProcessor 實例是在其自己的線程中完成解析工作的;
【4】HttpProcessor類(主要講解該類的assign方法的異步實現) 0)HttpProcessor類中另一個重要的方法是其私有方法process() 方法:該方法負責解析 HTTP請求,并調用相應的servlet容器的invoke方法; private void process(Socket socket) {boolean ok = true;boolean finishResponse = true;SocketInputStream input = null;OutputStream output = null;// Construct and initialize the objects we will needtry {input = new SocketInputStream(socket.getInputStream(),connector.getBufferSize());} catch (Exception e) {log("process.create", e);ok = false;}keepAlive = true;while (!stopped && ok && keepAlive) {finishResponse = true;try {request.setStream(input);request.setResponse(response);output = socket.getOutputStream();response.setStream(output);response.setRequest(request);((HttpServletResponse) response.getResponse()).setHeader("Server", SERVER_INFO);} catch (Exception e) {log("process.create", e);ok = false;}// Parse the incoming requesttry {if (ok) {parseConnection(socket);parseRequest(input, output);if (!request.getRequest().getProtocol().startsWith("HTTP/0"))parseHeaders(input);if (http11) {// Sending a request acknowledge back to the client if// requested.ackRequest(output);// If the protocol is HTTP/1.1, chunking is allowed.if (connector.isChunkingAllowed())response.setAllowChunking(true);}}} catch (EOFException e) {// It's very likely to be a socket disconnect on either the // client or the serverok = false;finishResponse = false;} catch (ServletException e) {ok = false;try {((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_BAD_REQUEST);} catch (Exception f) {;}} catch (InterruptedIOException e) {if (debug > 1) {try {log("process.parse", e);((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_BAD_REQUEST);} catch (Exception f) {;}}ok = false;} catch (Exception e) {try {log("process.parse", e);((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_BAD_REQUEST);} catch (Exception f) {;}ok = false;}// Ask our Container to process this requesttry {((HttpServletResponse) response).setHeader("Date", FastHttpDateFormat.getCurrentDate());if (ok) {connector.getContainer().invoke(request, response); // process method invokes the invoke method of corresponding servlet container}} catch (ServletException e) {log("process.invoke", e);try {((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);} catch (Exception f) {;}ok = false;} catch (InterruptedIOException e) {ok = false;} catch (Throwable e) {log("process.invoke", e);try {((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);} catch (Exception f) {;}ok = false;}// Finish up the handling of the requestif (finishResponse) {try {response.finishResponse();} catch (IOException e) {ok = false;} catch (Throwable e) {log("process.invoke", e);ok = false;}try {request.finishRequest();} catch (IOException e) {ok = false;} catch (Throwable e) {log("process.invoke", e);ok = false;}try {if (output != null)output.flush();} catch (IOException e) {ok = false;}}// We have to check if the connection closure has been requested// by the application or the response stream (in case of HTTP/1.0// and keep-alive).if ( "close".equals(response.getHeader("Connection")) ) {keepAlive = false;}// End of request processingstatus = Constants.PROCESSOR_IDLE;// Recycling the request and the response objectsrequest.recycle();response.recycle();}try {shutdownInput(input);socket.close();} catch (IOException e) {;} catch (Throwable e) {log("process.invoke", e);}socket = null;} 1)在Tomcat的默認連接器中,HttpProcessor類實現了 java.lang.Runnable 接:這樣,每個HttpProcessor實例就可以運行在自己的線程中了,稱為“處理器線程”。為每個?HttpProcessor 對象創建?HttpProcessor 實例后,會調用其start方法,啟動HttpProcessor 實例的處理器線程;(下面是?HttpProcessor類中的run方法的實現)(干貨——注意區分開HttpProcessor.run方法和 HttpConnector.run方法 ) public void run() { // HttpProcessor.run()// Process requests until we receive a shutdown signalwhile (!stopped) {// Wait for the next socket to be assignedSocket socket = await(); // this line, <span style="font-family: 宋體; font-size: 16px; line-height: 24px;">run方法的while循環執行到 await方法時會阻塞</span>if (socket == null)continue;// Process the request from this sockettry {process(socket);} catch (Throwable t) {log("process.invoke", t);}// Finish up this requestconnector.recycle(this);}// Tell threadStop() we have shut ourselves down successfullysynchronized (threadSync) {threadSync.notifyAll();}} private synchronized Socket await() { // HttpProcessor.await()// Wait for the Connector to provide a new Socketwhile (!available) {try {wait();} catch (InterruptedException e) {}}// Notify the Connector that we have received this SocketSocket socket = this.socket;available = false;notifyAll();if ((debug >= 1) && (socket != null))log(" The incoming request has been awaited");return (socket);} 對以上代碼的分析(Analysis): A1)run方法中的while循環做如下幾件事情:獲取套接字對象,進行處理,調用連接器的recycle() 方法將當前的 HttpRequest實例壓回棧中。 A2)下面是 HttpConnector類中 recycle方法的代碼:? */void recycle(HttpProcessor processor) {// if (debug >= 2)// log("recycle: Recycling processor " + processor);processors.push(processor);} A3)run方法的while循環執行到 await方法時會阻塞。await方法會阻塞處理器線程的控制流,直到它從HttpConnector中獲得了新的Socket對象。即,直到HttpConnector對象調用 HttpProcessor實例的assign方法前,都會一直阻塞; 但是,await方法 和assign方法并不是運行在同一個線程中的。assign方法是從 HttpConnector對象的 run方法中調用的。我們稱 HttpConnector實例中run方法運行時所在的線程為“連接器線程”。通過使用available的布爾變量和 Object.wait() 方法 和 notifyAll() 方法來進行溝通的; /*** Await a newly assigned Socket from our Connector, or <code>null</code>* if we are supposed to shut down.*/private synchronized Socket await() {// Wait for the Connector to provide a new Socketwhile (!available) {try {wait();} catch (InterruptedException e) {}}// Notify the Connector that we have received this SocketSocket socket = this.socket;available = false;notifyAll();if ((debug >= 1) && (socket != null))log(" The incoming request has been awaited");return (socket);} Attention) A1)wait方法會使當前線程進入等待狀態,直到其他線程調用了這個對象的notify() 方法和notifyAll方法; A2)下表總結了 await方法和 assign方法的程序流;
Why) W1)為什么 await方法要使用一個局部變量 socket,而不直接將成員變量socket返回呢? 因為使用局部變量可以在當前Socket對象處理完之前,繼續接收下一個Socket對象; W2)為什么 await方法需要調用notifyAll方法呢?是為了防止出現另一個Socket對象以及到達,而此時變量available的值還是true的case。在這種case下,連接器線程會在assign方法內的循環中阻塞,知道處理器線程調用了 notifyAll方法;
【5】Request對象(繼承了 RequestBase) 【6】Response對象 【7】處理請求(重點討論 HttpProcessor類的 process方法) 1)process方法執行以下3個操作: 解析連接, 解析請求, 解析請求頭 2)intro to process method: 2.1)通過在Connector接口中設置緩沖區的大小,任何人都可以使用連接器來設置緩沖區的大小; private void process(Socket socket) { // HttpProcessor.process()boolean ok = true;boolean finishResponse = true;SocketInputStream input = null;OutputStream output = null;// Construct and initialize the objects we will needtry {input = new SocketInputStream(socket.getInputStream(),connector.getBufferSize());} catch (Exception e) {log("process.create", e);ok = false;}keepAlive = true;while (!stopped && ok && keepAlive) {finishResponse = true;try {request.setStream(input);request.setResponse(response);output = socket.getOutputStream();response.setStream(output);response.setRequest(request);((HttpServletResponse) response.getResponse()).setHeader("Server", SERVER_INFO);} catch (Exception e) {log("process.create", e);ok = false;}// Parse the incoming requesttry {if (ok) {parseConnection(socket); // step1:解析連接parseRequest(input, output); // step2:解析請求if (!request.getRequest().getProtocol() .startsWith("HTTP/0"))parseHeaders(input); // step3:解析請求頭if (http11) {// Sending a request acknowledge back to the client if// requested.ackRequest(output);// If the protocol is HTTP/1.1, chunking is allowed.if (connector.isChunkingAllowed())response.setAllowChunking(true);}}} catch (EOFException e) {// It's very likely to be a socket disconnect on either the // client or the serverok = false;finishResponse = false;} catch (ServletException e) {ok = false;try {((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_BAD_REQUEST);} catch (Exception f) {;}} catch (InterruptedIOException e) {if (debug > 1) {try {log("process.parse", e);((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_BAD_REQUEST);} catch (Exception f) {;}}ok = false;} catch (Exception e) {try {log("process.parse", e);((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_BAD_REQUEST);} catch (Exception f) {;}ok = false;}// Ask our Container to process this requesttry {((HttpServletResponse) response).setHeader("Date", FastHttpDateFormat.getCurrentDate());if (ok) {connector.getContainer().invoke(request, response);}} catch (ServletException e) {log("process.invoke", e);try {((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);} catch (Exception f) {;}ok = false;} catch (InterruptedIOException e) {ok = false;} catch (Throwable e) {log("process.invoke", e);try {((HttpServletResponse) response.getResponse()).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);} catch (Exception f) {;}ok = false;}// Finish up the handling of the requestif (finishResponse) {try {response.finishResponse();} catch (IOException e) {ok = false;} catch (Throwable e) {log("process.invoke", e);ok = false;}try {request.finishRequest();} catch (IOException e) {ok = false;} catch (Throwable e) {log("process.invoke", e);ok = false;}try {if (output != null)output.flush();} catch (IOException e) {ok = false;}}// We have to check if the connection closure has been requested// by the application or the response stream (in case of HTTP/1.0// and keep-alive).if ( "close".equals(response.getHeader("Connection")) ) {keepAlive = false;}// End of request processingstatus = Constants.PROCESSOR_IDLE;// Recycling the request and the response objectsrequest.recycle();response.recycle();}try {shutdownInput(input);socket.close();} catch (IOException e) {;} catch (Throwable e) {log("process.invoke", e);}socket = null;} 2.2)然后是while循環,在該循環內,不斷讀入輸入流,知道HttpProcessor 實例終止,拋出一個異常,或連接斷開; // Parse the incoming requesttry { // there code are located in HttpProcessor.process() method.if (ok) {parseConnection(socket);parseRequest(input, output);if (!request.getRequest().getProtocol().startsWith("HTTP/0"))parseHeaders(input);if (http11) {// Sending a request acknowledge back to the client if// requested.ackRequest(output);// If the protocol is HTTP/1.1, chunking is allowed.if (connector.isChunkingAllowed())response.setAllowChunking(true);}}} 【7.1】解析連接 1)parseConnection() 方法:會從套接字中獲取Internet地址,將其賦值給 HttpRequestImpl 對象;此外,它還要檢查是否使用了代理,將Socket對象賦值給 request對象; private void parseConnection(Socket socket) // HttpProcessor.parseConnection()throws IOException, ServletException {if (debug >= 2)log(" parseConnection: address=" + socket.getInetAddress() +", port=" + connector.getPort());((HttpRequestImpl) request).setInet(socket.getInetAddress());if (proxyPort != 0)request.setServerPort(proxyPort);elserequest.setServerPort(serverPort);request.setSocket(socket);} 【7.2】解析請求 【7.3】解析請求頭 1)默認連接器中的parseHeaders() 方法:使用了 org.apache.catalina.connector.http 包內的HttpHeader類和 DefaultHeader類。HttpHeader類表示一個HTTP 請求頭。HttpHeader 類使用了字符數組來避免高代價的字符串操作。DefaultHeaders類是一個final類,包含了 字符數組形式的標準HTTP請求頭: final class DefaultHeaders {// -------------------------------------------------------------- Constantsstatic final char[] AUTHORIZATION_NAME = "authorization".toCharArray();static final char[] ACCEPT_LANGUAGE_NAME = "accept-language".toCharArray();static final char[] COOKIE_NAME = "cookie".toCharArray();static final char[] CONTENT_LENGTH_NAME = "content-length".toCharArray();static final char[] CONTENT_TYPE_NAME = "content-type".toCharArray();static final char[] HOST_NAME = "host".toCharArray();static final char[] CONNECTION_NAME = "connection".toCharArray();static final char[] CONNECTION_CLOSE_VALUE = "close".toCharArray();static final char[] EXPECT_NAME = "expect".toCharArray();static final char[] EXPECT_100_VALUE = "100-continue".toCharArray();static final char[] TRANSFER_ENCODING_NAME ="transfer-encoding".toCharArray();static final HttpHeader CONNECTION_CLOSE =new HttpHeader("connection", "close");static final HttpHeader EXPECT_CONTINUE =new HttpHeader("expect", "100-continue");static final HttpHeader TRANSFER_ENCODING_CHUNKED =new HttpHeader("transfer-encoding", "chunked"); 2)parseHeaders() 方法使用while循環讀取所有的HTTP 請求信息。調用request對象的 allocateHeader方法獲取一個內容為空的 HttpHeader實例開始。然后該實例被傳入SocketInputStream 實例的readHeader方法中: private void parseHeaders(SocketInputStream input) // HttpProcessor.parseHeaders()throws IOException, ServletException {while (true) {HttpHeader header = request.allocateHeader();// Read the next headerinput.readHeader(header);if (header.nameEnd == 0) {if (header.valueEnd == 0) {return;} else {throw new ServletException(sm.getString("httpProcessor.parseHeaders.colon"));}}String value = new String(header.value, 0, header.valueEnd);if (debug >= 1)log(" Header " + new String(header.name, 0, header.nameEnd)+ " = " + value);......request.nextHeader();}} 3)若所有的請求頭都已經讀取過了,則readHeader()方法不會再給 HttpHeader 實例設置name屬性了。就退出parseHeader方法了: if (header.nameEnd == 0) {if (header.valueEnd == 0) {return;} else {throw new ServletException(sm.getString("httpProcessor.parseHeaders.colon"));}} 【8】簡單的Container 應用程序 1)SimpleContainer類實現了 org.apache.catalina.Container接口,這樣它就可以與默認連接器進行關聯。? public class SimpleContainer implements Container { // just demonstrate a core method invoke.public void invoke(Request request, Response response)throws IOException, ServletException {String servletName = ( (HttpServletRequest) request).getRequestURI();servletName = servletName.substring(servletName.lastIndexOf("/") + 1);URLClassLoader loader = null;try {URL[] urls = new URL[1];URLStreamHandler streamHandler = null;File classPath = new File(WEB_ROOT);String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString() ;urls[0] = new URL(null, repository, streamHandler);loader = new URLClassLoader(urls);}catch (IOException e) {System.out.println(e.toString() );}Class myClass = null;try {myClass = loader.loadClass("servlet." + servletName);}catch (ClassNotFoundException e) {System.out.println(e.toString());}Servlet servlet = null;try {servlet = (Servlet) myClass.newInstance();servlet.service((HttpServletRequest) request, (HttpServletResponse) response);}catch (Exception e) {System.out.println(e.toString());}catch (Throwable e) {System.out.println(e.toString());}} Attention)我總結了一張Tomcat默認連接器測試用例的大致調用過程
/*** Await a newly assigned Socket from our Connector, or <code>null</code>* if we are supposed to shut down.*/private synchronized Socket await() { //HttpProcessor.awati() 方法// Wait for the Connector to provide a new Socketwhile (!available) {try {wait();} catch (InterruptedException e) {}}// Notify the Connector that we have received this SocketSocket socket = this.socket;available = false;notifyAll();if ((debug >= 1) && (socket != null))log(" The incoming request has been awaited");return (socket);} 對以上代碼的分析(Analysis): A1)HttpConnector類的大致工作: step1)initialize方法:調用該類的open方法創建服務器套接字; step2)start方法:開啟一個線程,該線程中有一個while循環,不斷接收client發送的HTTP連接請求,接著調用其類的createProcessor方法; step3)createProcessor方法:調用其類的 newProcessor方法; step4)newProcessor方法:創建HttpProcessor(HTTP連接器的支持類,HTTP請求處理器),利用HttpProcessor實例開啟一個線程,調用 HttpProcessor.run()方法;(轉向HttpProcessor類的run方法)(干貨中的干貨——也即當clients 發出http 連接請求后,HttpConnector 在while循環中創建HttpConnector的支持類 HttpProcessor,Http處理器類,并調用該類的start方法,開啟線程,即while循環為每一個client 請求 開啟一個線程進行處理,多么巧妙) A2)HttpProcessor類的大致工作: step1)run方法:傳入套接字參數,并調用process方法; step2)process方法:依次調用 parseConnection()方法, parseRequest()方法, parseHeader() 方法: 上述3個方法的作用參見本文章節【7】(也可以參見下面的補充);調用上述三個方法后,會調用連接器HttpConnector實例的關聯容器的invoke方法;(轉向container的invoke方法) step3)SimleContainer.invoke方法:invoke方法聲明為,invoke(Request request, Response response):(見下面的代碼實例) step3.1)創建類加載器; step3.2)利用類加載器集合request中的請求URI(HttpProcessor.parseReqeust解析出的請求URI),加載請求的servlet,創建該servlet實例并調用其service方法(service方法接著就會向client發送響應信息),ending; public final class Bootstrap {public static void main(String[] args) {HttpConnector connector = new HttpConnector();SimpleContainer container = new SimpleContainer(); // 創建容器connector.setContainer(container); // 將該 容器 和 http連接器 相關聯try {connector.initialize();connector.start();// make the application wait until we press any key.System.in.read();}catch (Exception e) {e.printStackTrace();}} }
補充-Complementary begins) C1)HttpProcessor.parseConnection方法:會從套接字中獲取internet地址,端口號,協議等信息; C2)HttpProcessor.parseRequest方法:會解析請求體的第一行請求信息(請求方法——URI——協議/版本); C3)HttpProcessor.parseHeader方法:解析請求體中的請求頭信息,還會附加解析cookie信息; 補充-Complementary ends)

補充-Complementary2 begins)在補充一個知識點(request和response是何時創建的?——其實在HttpProcessor 構造器中就已經創建了) public HttpProcessor(HttpConnector connector, int id) {super();this.connector = connector;this.debug = connector.getDebug();this.id = id;this.proxyName = connector.getProxyName();this.proxyPort = connector.getProxyPort();this.request = (HttpRequestImpl) connector.createRequest();this.response = (HttpResponseImpl) connector.createResponse();this.serverPort = connector.getPort();this.threadName ="HttpProcessor[" + connector.getPort() + "][" + id + "]";} public Request createRequest() { HttpRequestImpl request = new HttpRequestImpl();request.setConnector(this);return (request);}public Response createResponse() {HttpResponseImpl response = new HttpResponseImpl();response.setConnector(this);return (response);}補充-Complementary2 ends)
【9】運行應用程序 9.1)運行參數 E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\src>java -cp .;lib/servlet.jar;lib/catalina_4_1_24.jar;E:\bench-cluster\cloud-data-preprocess\HowTomcatWorks\webroot com.tomcat.chapter4.startup.Bootstrap HttpConnector Opening server socket on all host IP addresses HttpConnector[8080] Starting background thread from service from service 9.2)運行結果

總結

以上是生活随笔為你收集整理的tomcat(4)Tomcat的默认连接器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

www.亚洲激情.com | 99麻豆久久久国产精品免费 | 一区二区三区中文字幕在线 | 国产一区二区三区网站 | 国产精品久久久久久久久久久久午夜片 | 国产69久久精品成人看 | 超碰在线免费福利 | 97超碰超碰久久福利超碰 | 成人午夜网址 | 91在线影院 | 97视频在线观看免费 | 欧美日韩调教 | 黄色app网站在线观看 | 米奇狠狠狠888 | 国产一区二区在线播放 | 在线观看小视频 | 国产精品成人av在线 | 超碰免费观看 | 丁香久久五月 | 免费看的黄网站 | 自拍超碰在线 | 操操综合 | 日日夜夜人人精品 | 美女国内精品自产拍在线播放 | 日韩成人精品 | 五月激情站 | 久久99影院 | 色在线高清 | 91人人视频在线观看 | 黄网站a| 国产成人99久久亚洲综合精品 | 国产美女视频免费观看的网站 | 97人人视频 | 国产成人av在线 | 久久69精品 | 天天草天天干天天射 | 国产视频一区在线 | 中文字幕黄色 | 午夜精品av | 国产成人一区二区三区免费看 | 国产精品初高中精品久久 | 国产精品一区二区美女视频免费看 | 午夜影院三级 | 欧美a级一区二区 | 国产 一区二区三区 在线 | 国产一区在线看 | 99爱这里只有精品 | 99re6热在线精品视频 | 一级黄色在线视频 | 久精品视频 | 国产黄色在线观看 | 欧美日韩在线免费观看 | 福利二区视频 | 91精选| 四虎国产精品免费 | 日本中文在线播放 | 99精品视频在线观看视频 | 激情六月婷婷久久 | 亚洲精品在线国产 | 久久成人国产精品 | 欧美日韩国产精品一区二区 | 二区视频在线 | 国产护士hd高朝护士1 | 国产精品久久久久免费 | 亚洲国产成人精品电影在线观看 | 人人插人人玩 | 91精品秘密在线观看 | 免费色网站 | 91综合视频在线观看 | 亚洲免费在线观看视频 | 成年人在线免费看视频 | 国产黄色片在线免费观看 | 日韩电影在线视频 | 欧美国产日韩在线视频 | 韩国精品在线 | 亚洲精品资源在线 | 免费在线观看成人 | 免费久久片 | 国产亚洲激情视频在线 | 日韩av资源在线观看 | 精品视频一区在线观看 | 免费看污在线观看 | 日韩在线 一区二区 | 国产免费影院 | 精品国产乱码久久久久久天美 | 成年人免费观看国产 | 日日操日日 | 国产综合精品一区二区三区 | 中文字幕乱码在线播放 | 欧美大片www | 国产成人精品综合久久久 | 免费在线观看黄 | 色香蕉网 | 久久噜噜少妇网站 | 久久久久www| 亚洲日本色 | 日日操天天操狠狠操 | 中文字幕在线观看资源 | 黄网在线免费观看 | 国产在线成人 | 国产免费成人 | 国产精品96久久久久久吹潮 | 亚洲欧美日韩中文在线 | 国产打女人屁股调教97 | 成人丝袜| 亚洲欧美国产精品18p | 亚洲无吗av | 天天艹天天| 人人射人人射 | 九九热国产视频 | 在线观看岛国 | 狠狠色狠狠色综合日日92 | 男女靠逼app | 日日夜夜精品视频天天综合网 | 91精品日韩| 看片一区二区三区 | 在线观看视频精品 | 午夜久久久久久久久久久 | 男女激情麻豆 | 天天色天天射天天操 | 精品国产一区二区三区在线观看 | 国产成人精品一区在线 | 国产在线视频在线观看 | 手机看片99| 国产成人精品一区二区三区福利 | 久久韩国免费视频 | 成人在线你懂得 | 欧美日韩一区二区在线观看 | 日本在线观看中文字幕无线观看 | 久久99精品国产麻豆宅宅 | 精品国产欧美 | 91视频免费 | 国产精品一区二区三区四区在线观看 | 午夜精品区 | 免费看国产精品 | 免费在线激情视频 | 亚洲激情综合 | 黄色福利视频网站 | 国产午夜激情视频 | 国产精品123| 99视频网站 | 日本在线免费看 | 久久99久久99免费视频 | 在线视频欧美日韩 | 亚洲第五色综合网 | 亚洲欧美激情精品一区二区 | 蜜桃麻豆www久久囤产精品 | 免费一级片在线观看 | 国产五十路毛片 | 免费在线成人 | 欧美激情综合五月色丁香 | 69视频在线播放 | 中文字幕一区二区三区乱码不卡 | 欧美日韩1区 | 欧美日韩国产精品一区二区亚洲 | 人人草人 | 久久视频网址 | 美女免费网站 | 亚洲婷婷在线 | 国产精品激情偷乱一区二区∴ | 久久三级视频 | 午夜骚影 | 999男人的天堂 | 国产精品2区 | 视频在线观看国产 | 精品亚洲免费视频 | 国内视频1区 | 九九色在线观看 | 伊人网站 | www.av免费观看 | 欧美精品二 | 欧美 国产 视频 | 碰超人人 | 天天爱av导航 | 在线视频a | 91久久黄色| 日韩欧美一区二区三区免费观看 | 成年人免费在线观看网站 | 中文字幕乱码日本亚洲一区二区 | 久久久久久久久久网站 | 国产亚洲精品久久19p | 亚洲每日更新 | 精品一区二区三区久久久 | 欧美日韩在线观看一区二区三区 | a午夜电影| av电影免费在线 | 国产做a爱一级久久 | 在线观看亚洲视频 | 午夜婷婷网 | 国产四虎影院 | 国产资源精品在线观看 | 久久免费电影 | 国产精品久久久久久久久久东京 | 国产你懂的在线 | 天天综合在线观看 | 亚洲va在线va天堂va偷拍 | 国内视频在线观看 | 国产一区二区在线免费视频 | 久久成人精品电影 | 国内综合精品午夜久久资源 | 干 操 插| 亚洲干| 在线播放视频一区 | 亚洲国产精品成人av | 国产精品一区二区吃奶在线观看 | 麻豆影视在线播放 | 亚洲精品在线一区二区 | www狠狠| 一区二区视频播放 | 在线观看国产v片 | 免费网址在线播放 | 精品久久网 | 亚洲免费av电影 | 在线观看亚洲电影 | 国产美女视频一区 | 国产探花| 日日夜夜天天综合 | 草久在线观看视频 | 中文字幕人成乱码在线观看 | 亚洲一级电影 | 91福利在线导航 | 国产免费又黄又爽 | 亚洲女人天堂成人av在线 | 欧美精品v国产精品v日韩精品 | 九九九九免费视频 | 91福利视频免费 | 2021av在线 | 中文字幕黄网 | 四虎在线免费 | 成人在线网站观看 | 欧美九九九 | 国产黄网站在线观看 | 绯色av一区 | 久久乱码卡一卡2卡三卡四 五月婷婷久 | 欧美日韩在线视频一区 | 最近中文字幕视频完整版 | 亚洲激情中文 | 色综合天天狠狠 | 国产成人一区二区啪在线观看 | 国产中文在线播放 | 欧美伦理一区 | 国产一区在线免费观看 | 美腿丝袜一区二区三区 | www.色五月.com | 免费的黄色的网站 | 中午字幕在线 | 中文区中文字幕免费看 | 久久久免费国产 | 在线黄色免费 | 久久丝袜视频 | 特级黄色片免费看 | 午夜av免费观看 | 久久国产一二区 | 天天综合网久久综合网 | 欧美色图一区 | 亚洲精品在线观看av | 天天射射天天 | 国产破处在线播放 | 日韩免费高清在线观看 | 国产精品久久久久久一二三四五 | 国产视频日本 | 麻豆av电影 | 99在线热播精品免费99热 | 日韩欧美高清 | 色综合久久天天 | 色综合色综合色综合 | 在线观看亚洲免费视频 | 久99视频 | 精品久久免费 | 午夜999 | 亚洲日本中文字幕在线观看 | 日韩欧美高清一区二区三区 | 国产日韩欧美在线看 | av专区在线 | 91人人网 | 综合久久久久久久久 | 免费在线观看av网站 | www色com| 丁香花中文字幕 | 91专区在线观看 | 久久综合九色99 | 91在线影视| 成人97视频 | 99精品欧美一区二区蜜桃免费 | 99热99| 日本aaa在线观看 | 久久婷婷国产 | 日韩av片免费在线观看 | 91免费版成人 | av在线播放一区二区三区 | 黄色的视频 | 99久久久久国产精品免费 | 五月婷婷色综合 | wwxxxx日本 | 日韩色一区二区三区 | 日韩av视屏 | 字幕网资源站中文字幕 | 99中文字幕| 国产高清视频在线观看 | 成人一级片视频 | 6080yy精品一区二区三区 | 中文字幕亚洲不卡 | 久久精品一区二区三区中文字幕 | 天堂av在线7| 中文字幕视频一区二区 | 国产免费高清视频 | 亚洲免费视频在线观看 | 在线免费中文字幕 | 91精品一区二区三区蜜臀 | 91插插影库| 最新色站 | 91色一区二区三区 | 97av视频| 欧美一二三区在线播放 | 亚洲区另类春色综合小说校园片 | av综合av | 国产精品免费一区二区 | 涩涩网站在线观看 | 黄色福利网 | 射综合网 | 国产精品岛国久久久久久久久红粉 | 欧美成人精品欧美一级乱 | 国产不卡在线视频 | 国产精品一区二区三区久久久 | 国产精品美女久久久网av | 三上悠亚一区二区在线观看 | 欧美精品久久久 | 97电影手机版 | 成人国产亚洲 | 在线免费视频一区 | 久草免费在线观看 | 最新日韩电影 | 中文字幕免费成人 | 久久国产成人午夜av影院宅 | 国产丝袜制服在线 | 国产麻豆视频免费观看 | 精品一二三区 | 久久成人在线 | 天天天干夜夜夜操 | 久久亚洲欧美日韩精品专区 | 欧美日本中文字幕 | 国产亚洲精品中文字幕 | 午夜精品视频在线 | 久草在线在线视频 | 美女视频免费一区二区 | 成人永久在线 | 久草网站 | 丁香九月婷婷综合 | 在线观看免费成人 | 免费在线激情电影 | 四虎成人免费观看 | 亚洲精品麻豆视频 | 99久久99久久 | 91人人揉日日捏人人看 | 1024久久| 国产99视频在线观看 | 少妇精品久久久一区二区免费 | 免费福利在线视频 | 精品久久久久国产免费第一页 | 日韩爱爱片 | 国内精品久久久久久久久久久久 | 国产蜜臀av| 色噜噜在线观看 | 久久综合婷婷国产二区高清 | 99麻豆久久久国产精品免费 | 免费精品在线观看 | 99热在线国产 | 97在线观看 | h视频在线看 | 波多野结衣资源 | www.91av在线| 国产精品大全 | 99热在线国产精品 | 久久久91精品国产一区二区精品 | 国产黄色一级大片 | 亚洲精品色 | 天天射天天色天天干 | 激情五月色播五月 | 欧美最猛性xxx | 国产一区二区精品久久91 | 黄a在线看| 国内成人av | 久久艹综合 | 日韩天天干 | 国产69精品久久久久久 | 日韩中文字幕亚洲一区二区va在线 | 欧美一性一交一乱 | 毛片美女网站 | 精品国产精品一区二区夜夜嗨 | 婷婷六月网 | www.久久成人 | 国产 在线 日韩 | 在线观看免费观看在线91 | 国产最新在线 | 国内精品久久久 | 国产一区免费观看 | 国产一级电影网 | 国产成人av综合色 | 久久综合综合久久综合 | 亚洲精品久久激情国产片 | 亚洲欧美国产精品 | 亚洲视频在线免费看 | 国产色综合天天综合网 | 亚洲综合在线观看视频 | 日韩在线播放av | 九九免费观看全部免费视频 | 国产精品 中文字幕 亚洲 欧美 | 久久96| 国色天香永久免费 | 久久婷婷色综合 | 亚洲不卡123 | 国产剧情在线一区 | 青青草国产精品 | 日韩在线视频一区二区三区 | 国产在线精品观看 | 丁香花在线视频观看免费 | 欧美资源 | 六月丁香综合网 | 亚洲年轻女教师毛茸茸 | 亚洲精品91天天久久人人 | 国产精品免费不 | 中文字幕观看视频 | 最新日本中文字幕 | 丝袜精品视频 | 四虎影视www | 免费精品 | 日韩欧美高清视频在线观看 | 狠狠色丁香久久婷婷综合五月 | 九草视频在线 | 免费观看一级成人毛片 | 中文字幕亚洲五码 | 91精品国产92久久久久 | 久久综合久久综合久久综合 | 久久九九国产精品 | 99久久精品免费看国产 | 国产精品福利小视频 | 午夜国产福利在线观看 | 亚洲激情婷婷 | 日韩三级视频在线观看 | 久久久久婷 | 91porny九色在线播放 | 亚洲资源视频 | 999成人| 中文字幕在线观看免费高清完整版 | 久久这里有精品 | 久久人人爽爽人人爽人人片av | 黄色成人小视频 | 中文字幕精品三区 | 九色91福利| 五月天久久婷 | 久久成人18免费网站 | 亚洲国产美女久久久久 | 国产1区2区3区在线 亚洲自拍偷拍色图 | 中文字幕最新精品 | 亚洲不卡在线 | 8x成人免费视频 | 五月婷婷丁香在线观看 | 三级在线视频观看 | 亚洲毛片在线观看. | 中文字幕视频观看 | 国产97视频 | 福利视频区 | 精品久久久网 | 99视频精品全部免费 在线 | 亚洲精区二区三区四区麻豆 | 久久综合婷婷国产二区高清 | 精品久久五月天 | 日韩中文在线播放 | 亚洲国产丝袜在线观看 | 成 人 黄 色 片 在线播放 | 激情五月婷婷激情 | av免费观看在线 | 伊人久久在线观看 | 伊人午夜视频 | 婷婷色社区 | 中文字幕一区二区三区四区在线视频 | 亚洲va欧美va人人爽春色影视 | 国产精品免费久久久久久久久久中文 | 天堂麻豆 | 99久久这里有精品 | 国产精品精品久久久 | 啪嗒啪嗒免费观看完整版 | 在线观看深夜视频 | 丁香激情综合久久伊人久久 | 久久无码精品一区二区三区 | 久久婷婷丁香 | 激情综合五月天 | 香蕉视频网站在线观看 | 免费看毛片网站 | 免费视频xnxx com| 久久热首页 | 亚洲日本在线一区 | 亚洲国产欧洲综合997久久, | 久久好看免费视频 | 色av婷婷 | 国产v在线播放 | 91在线91| 91精品日韩 | 亚洲精品tv久久久久久久久久 | 国产一区二区三区免费在线观看 | 激情中文在线 | 国产色视频网站 | 天天天天天天干 | 色噜噜狠狠狠狠色综合久不 | 日韩欧美在线视频一区二区 | 国产中文字幕一区二区 | 亚洲精品99 | 久久婷婷国产色一区二区三区 | 国产在线一区二区三区播放 | 成人h视频在线播放 | 国产一区在线免费观看 | 国产视频资源在线观看 | 国内99视频 | 欧美 日韩 性 | 国产精品欧美一区二区 | 色wwwww | 99精品久久久 | 中文字幕人成乱码在线观看 | 亚洲精品视频免费观看 | 伊人电影天堂 | 成人av手机在线 | 久久久免费看视频 | 免费观看www视频 | 很黄很污的视频网站 | 在线观看亚洲a | 99精品视频在线观看 | 高清一区二区三区av | 国产精品九九久久99视频 | 韩国av电影网 | 国产视频一区二区在线 | 亚洲综合网站在线观看 | 成人黄色在线电影 | 天天草天天 | 最新中文在线视频 | 一区精品久久 | 九色琪琪久久综合网天天 | 欧美日韩成人一区 | 成人性生交视频 | 久久久久久福利 | 黄色小说在线观看视频 | 久久精品国产亚洲精品 | 91欧美视频网站 | 久草在线免费色站 | 日韩v在线91成人自拍 | 欧美日韩国产高清视频 | 91av视频免费在线观看 | 日日久视频 | 成人一级片视频 | 97国产精品免费 | 国产一级免费电影 | 午夜电影av | 99久久99久国产黄毛片 | 97视频免费在线看 | 精品国产aⅴ一区二区三区 在线直播av | 日本精品一区二区 | 一二区电影 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 69久久久久久久 | 天天干天天操天天拍 | 成人免费网站在线观看 | 国产精品久久久久久一区二区 | 久久黄色小说 | 福利视频 | 亚洲第一久久久 | 精品国产精品国产偷麻豆 | 91亚洲精品国偷拍自产在线观看 | 手机看片福利 | 嫩模bbw搡bbbb搡bbbb| 亚洲视频高清 | 亚洲首页 | 成人黄色国产 | 不卡的一区二区三区 | 久久99久| www国产精品com | 国产免费久久av | 久精品视频在线观看 | 免费在线观看成人 | 免费看短| 日韩| 午夜影院三级 | 91人人澡人人爽 | 碰超人人 | 一区二精品| 在线电影日韩 | 久久免费观看视频 | 久久久精品国产一区二区电影四季 | av先锋影音少妇 | 免费在线看成人av | 久久精彩免费视频 | 97成人免费视频 | 日韩精品视 | 欧美a级成人淫片免费看 | 国产精品久久久久久久电影 | 久久香蕉国产精品麻豆粉嫩av | 在线观看黄网站 | 精品超碰| 蜜桃久久久 | 国产四虎在线 | 久久久免费电影 | 超碰在线观看99 | 天天综合亚洲 | 黄av资源| 2019中文最近的2019中文在线 | 亚洲精品毛片一级91精品 | 日韩免费高清在线 | 久久精品系列 | 大片网站久久 | 成人全视频免费观看在线看 | 911久久香蕉国产线看观看 | 欧美日韩一区二区三区不卡 | 久久一区二区三区超碰国产精品 | 中文字幕亚洲国产 | 91麻豆视频 | 婷婷久久网 | 天天操天天射天天 | 国产成人精品一区二区三区免费 | 天天爽天天做 | 夜夜操天天操 | 性色视频在线 | 日韩精品在线观看av | 在线国产中文字幕 | 天天色综合1 | 99在线热播精品免费 | 天天曰| 999久久国产 | 99精品久久99久久久久 | 国产精品手机在线 | 91大神电影 | 亚洲色影爱久久精品 | 久久视频在线视频 | 日韩中文字幕免费视频 | 911av视频 | www.少妇| 美女网站在线免费观看 | 在线免费观看黄网站 | 欧美一区成人 | 麻豆久久精品 | 粉嫩av一区二区三区四区 | 99re亚洲国产精品 | 国产精品乱码久久久久久1区2区 | 天天射天天干天天操 | 黄污视频网站 | 久久成人国产 | 91福利在线导航 | 亚洲性少妇性猛交wwww乱大交 | 在线观看av中文字幕 | 免费国产在线精品 | 国产色网站 | 香蕉视频久久 | 国产精品国产三级国产 | 日韩高清久久 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 国产精品久久久久久五月尺 | 毛片随便看 | 超碰在线97观看 | 国产精品video | 六月丁香婷婷久久 | 久久免费视频网站 | 亚洲天堂免费视频 | 国产精品videoxxxx | 久久看视频 | 亚洲国产精品视频 | 久久综合电影 | 亚洲一区日韩 | 国产精品久久久久三级 | 亚洲在线看 | 99亚洲视频| 99精品视频免费观看 | www.大网伊人 | a黄色片 | 日韩二三区 | 久久久精品日本 | 中国精品少妇 | 国产色影院 | 97超碰精品 | 人人澡人人模 | 天天拍天天色 | 黄色aaaaa| 国产网红在线观看 | 国内精品久久久久久久影视简单 | 国产一区二区免费 | av一级一片 | 亚洲小视频在线观看 | 久久精品国产精品亚洲 | 亚洲午夜久久久综合37日本 | 成人免费在线视频 | 少妇bbw揉bbb欧美 | 亚洲欧美乱综合图片区小说区 | 欧美午夜性 | 97精品国产一二三产区 | 在线亚洲天堂网 | 国产视频精品在线 | 国产一级片直播 | 91欧美在线 | 91大神精品视频在线观看 | 91片在线观看 | 综合激情网 | 日韩国产精品毛片 | 国产激情电影综合在线看 | 色综合久久久久网 | 亚洲天堂精品视频在线观看 | 天天色天天干天天色 | 欧洲精品亚洲精品 | 中文字幕国产亚洲 | 久热免费在线 | 精品国产1区二区 | 91麻豆视频 | 天堂麻豆 | 天天爱天天草 | 国产精品久久一卡二卡 | 国产资源免费 | 婷五月激情 | 精品久久久久久久久久岛国gif | 色中射| 亚洲精品视频免费观看 | 青草视频免费观看 | 国产中文字幕一区 | 久久视频在线观看 | 在线免费观看国产黄色 | 日韩在线免费 | 亚洲性xxxx | 啪嗒啪嗒免费观看完整版 | 91探花在线 | 天天操天天射天天添 | 在线国产日本 | 亚洲一二区精品 | 狠狠狠狠狠狠狠狠 | 久久成人人人人精品欧 | 日韩精品免费在线观看视频 | 欧美亚洲国产精品久久高清浪潮 | 中日韩欧美精彩视频 | 久艹在线免费观看 | 亚洲国产免费看 | 92精品国产成人观看免费 | 久久免费中文视频 | 91精品国产亚洲 | 亚洲涩涩网 | 亚洲午夜精品久久久久久久久久久久 | 日韩毛片在线播放 | 亚洲视频分类 | 激情在线网址 | 一区二区视频在线免费观看 | 亚洲成人中文在线 | 国产精品日韩欧美一区二区 | 粉嫩av一区二区三区入口 | 亚洲免费a| 久久亚洲精品电影 | 国产成人黄色av | 成人黄色短片 | 91尤物国产尤物福利在线播放 | 狠狠久久婷婷 | 蜜桃视频成人在线观看 | av中文字幕亚洲 | 免费激情在线电影 | 欧美成人在线免费观看 | 国产午夜三级一区二区三桃花影视 | 欧美精品xx | 99精品免费久久久久久久久 | 99精品免费网 | 国产成人av网 | 日本免费久久高清视频 | 亚洲黄色区 | 黄色毛片视频免费观看中文 | 国产亚洲精品久久网站 | 国产视频日韩视频欧美视频 | 精品在线观看一区二区 | 日韩av免费一区二区 | 中文av网| 国产免费人人看 | 超碰在线cao | 激情久久综合网 | 天天插视频 | 99精品久久只有精品 | 色插综合 | 九九视频网 | 久草在线视频首页 | 黄色大片国产 | 美女黄色网在线播放 | 国产网红在线观看 | 日韩欧美在线观看一区 | 99精品观看| 国产一区视频在线播放 | 欧美精品久久久久久久久久 | 色播激情五月 | 国产九九九精品视频 | 亚洲精品午夜久久久 | 久久成人免费视频 | 国产亚洲精品久久网站 | 97人人精品| 日韩欧美极品 | 欧美一级免费高清 | 久久久久久毛片 | 探花国产在线 | 国产精品九九久久久久久久 | 69国产成人综合久久精品欧美 | 在线看福利av | 亚洲电影av在线 | 国产黄a三级三级三级三级三级 | 色人久久 | 午夜精品久久久久久久99热影院 | 国产成人精品一区一区一区 | 国产九色在线播放九色 | 亚洲第一av在线 | 欧美另类交在线观看 | 激情五月激情综合网 | 国产中文字幕久久 | 午夜精品久久久久久久99热影院 | 天天做日日做天天爽视频免费 | 免费一级日韩欧美性大片 | 人人干人人艹 | 伊人久在线| 日韩亚洲在线观看 | 国产午夜亚洲精品 | 天天操天天拍 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 蜜臀av在线一区二区三区 | 麻豆传媒精品 | 高清国产在线一区 | 久久国产精品视频免费看 | 91精品视频在线免费观看 | 天天草天天爽 | 国产精品一区二区三区在线播放 | 久久久久国产一区二区三区 | 国产一级电影在线 | 欧美日韩网址 | 九九视频网 | 欧美一区二区在线看 | 久久久久高清毛片一级 | 韩日电影在线免费看 | 91九色porn在线资源 | 狠狠插狠狠干 | 九九综合九九 | 天天操天天干天天操天天干 | 97超级碰碰碰碰久久久久 | 欧美久草视频 | 欧美日韩精品影院 | 色网站免费在线看 | 在线视频麻豆 | 99精品视频在线观看播放 | 播五月婷婷 | 久草亚洲视频 | 日韩国产精品毛片 | 久久国产免费看 | 久久国产精品精品国产色婷婷 | 国产黄色a| 天天操偷偷干 | 国产精品久久久久久久久久久久久久 | 亚洲精品9 | 69国产盗摄一区二区三区五区 | 青青草在久久免费久久免费 | 91免费在线 | 六月久久婷婷 | 看黄色.com | 久久久久免费网站 | 精品国产激情 | 高清av免费看 | 国产精品久久久久久久妇 | 丁香六月久久综合狠狠色 | av网站免费在线 | 在线免费性生活片 | 西西4444www大胆视频 | 97夜夜澡人人爽人人免费 | 亚洲视频中文 | 中文字幕免费高清av | 日本性生活一级片 | 91免费版在线观看 | 日韩精品中文字幕在线播放 | 国产综合精品久久 | av不卡免费在线观看 | 中文字幕 在线看 | 正在播放国产一区 | av看片在线 | 国产中文字幕在线免费观看 | 国产精品wwwwww | 国产精品第一页在线 | 特黄特黄的视频 | 免费在线色电影 | 91福利区一区二区三区 | 国产精品成人免费一区久久羞羞 | 亚洲精品中文在线 | 久久久久久久久久久黄色 | 国产精品18久久久久久久久久久久 | www黄色com | 91黄色免费网站 | 国产一级片不卡 | 免费合欢视频成人app | 国产精品视频最多的网站 | 久久精品站 | 色婷婷a| 天天操综合网站 | 日日碰狠狠躁久久躁综合网 | 国产不卡网站 | 久久夜夜爽 | 亚洲干视频在线观看 | 91麻豆免费视频 | 午夜av在线播放 | 中国一级片在线播放 | 激情五月在线 | 一级特黄aaa大片在线观看 | 欧美一级日韩三级 | 国产高h视频 | 亚洲视频免费视频 | a级国产乱理伦片在线播放 久久久久国产精品一区 | 五月婷婷丁香 | 狠狠狠色| 久久影院亚洲 | 成人高清在线观看 | 午夜狠狠操 | 精品在线视频一区二区三区 | 亚洲精品视频久久 | 免费黄色小网站 | 国产看片 色 | 国产尤物在线视频 | 国产黄色精品在线 | 日韩在线观看视频免费 | 国产精品免费大片视频 | 久久久久免费精品视频 | av黄网站 | 久久久免费精品视频 | 国产一区二区网址 | 亚洲永久精品国产 | 国产精品久久久久久999 | 一区二区三区手机在线观看 | 久久精品99国产精品亚洲最刺激 | 久久综合久久综合这里只有精品 | 五月天激情开心 | 国内精品中文字幕 | 久久爱资源网 | 黄色视屏免费在线观看 | 在线观看日韩中文字幕 | 日本中文字幕久久 | 国产区精品 | www.com.日本一级 | 色视频在线观看免费 | 天天色草 | 日韩中文字幕国产 | 成人97视频一区二区 | 国产一级二级在线播放 | 91免费视频网站在线观看 | 日本精品一区二区 | 国产精品人人做人人爽人人添 | 免费福利在线视频 | 99久久精品视频免费 | 伊人久久一区 | 欧美激情视频久久 | 探花视频网站 | 91亚洲精品久久久蜜桃 | 一区二区三区在线播放 | 国产精品美女 | 亚洲一级黄色大片 | 亚洲乱码国产乱码精品天美传媒 | 亚洲天天做 | 中日韩三级视频 | av一级二级 | 日韩中文字幕a | 亚洲成av人片在线观看www | 精品中文字幕视频 | 五月婷婷中文 | 国产成人免费 | 五月天狠狠操 | 91久久人澡人人添人人爽欧美 | 久久视频在线看 | 99热这里精品 | 麻豆高清免费国产一区 | 人人爽人人澡人人添人人人人 | 国产精品久久久久久999 | 欧美日韩国产一区二区三区 | 免费高清在线观看成人 | 亚洲永久精品一区 | 国产福利一区二区三区在线观看 | 日韩精品资源 | 五月天综合 | 福利视频网址 | 日韩国产欧美在线播放 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 久草久草在线观看 | 狠狠网站 | 亚洲无吗av | 国产精品久久久久四虎 | 免费福利在线视频 | 免费中文字幕 | 亚洲精品资源在线观看 | 久草电影免费在线观看 | 一区二区不卡视频在线观看 | 免费特级黄色片 | 欧美日韩一区二区久久 | 天天综合中文 | 午夜.dj高清免费观看视频 | 国产成人在线免费观看 | 国产综合婷婷 | 亚洲精品色视频 | 在线久草视频 | 国产精品一区二区三区久久 | 亚洲永久字幕 | www.天天成人国产电影 | 国产成人av福利 | 97国产情侣爱久久免费观看 | 中文字幕高清在线 |