日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

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

编程问答

getprivateprofilestring读不到数据_Tomcat NIO(11)请求数据读取

發布時間:2025/3/11 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 getprivateprofilestring读不到数据_Tomcat NIO(11)请求数据读取 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在上一篇文章里我們主要介紹了 tomcat?io?線程中涉及到的主要核心類,包括?AbstractProcessorLight,Http11Processor,CoyoteAdapter,這里主要介紹對于請求數據的讀取。

對于 tomcat 請求數據的讀取來說,可以分為請求行的讀取,請求頭的讀取,請求體的讀取,三個部分方法調用序列圖如下:

讀取請求行

讀取請求頭

讀取請求體

綜合上面三個序列圖,對于請求行,請求頭,請求體的讀取都最終調用了NioSocketWrapper 對象實例的 fillReadBuffer() 方法。只不過請求行和請求頭讀取參數傳遞為 true,請求體讀取參數傳遞為 false,該方法核心代碼如下:

private int fillReadBuffer(boolean block, ByteBuffer to) throws IOException { int nRead; NioChannel socket = getSocket(); if (socket instanceof ClosedNioChannel) { throw new ClosedChannelException(); } if (block) { Selector selector = null; try { selector = pool.get(); } catch (IOException x) { // Ignore } try { nRead = pool.read(to, socket, selector, getReadTimeout()); } finally { if (selector != null) { pool.put(selector); } } } else { nRead = socket.read(to); if (nRead == -1) { throw new EOFException(); } } return nRead;}
  • 根據上述方法分析,對于請求行和請求頭的讀取采用非阻塞的方式,用到了以前文章介紹的 NioChannel 對象的 read(ByteBuffer) 方法,其核心代碼如下:
//NioChannelprotected SocketChannel scpublic int read(ByteBuffer dst) throws IOException {????return?sc.read(dst);?}
  • 根據上述代碼,請求行和請求頭的讀取本質是調用 java NIO api SocketChannel 的 read() 方法,該方法為非阻塞方法。如果讀不到數據就直接返回,繼續由以前文章介紹的 poller 線程監測是否有數據可讀。
  • 對于請求體的讀取采用阻塞的方式,調用以前文章中介紹的 NioSelectorPool 的read(ByteBuffer buf, NioChannel socket, Selector selector, long readTimeout) 方法。在該方法中又會調用 NioBlockingSelector 的 read() 方法,核心代碼如下:

    public int read(ByteBuffer buf, NioChannel socket, long readTimeout) throws IOException { SelectionKey key = socket.getIOChannel().keyFor(socket.getSocketWrapper().getPoller().getSelector()); if (key == null) { throw new IOException(sm.getString("nioBlockingSelector.keyNotRegistered")); } KeyReference reference = keyReferenceStack.pop(); if (reference == null) { reference = new KeyReference(); } NioSocketWrapper att = (NioSocketWrapper) key.attachment(); int read = 0; boolean timedout = false; int keycount = 1; //assume we can read long time = System.currentTimeMillis(); //start the timeout timer try { while (!timedout) { if (keycount > 0) { //only read if we were registered for a read read = socket.read(buf); if (read != 0) { break; } } try { if (att.getReadLatch()==null || att.getReadLatch().getCount()==0) { att.startReadLatch(1); } poller.add(att,SelectionKey.OP_READ, reference); att.awaitReadLatch(AbstractEndpoint.toTimeout(readTimeout), TimeUnit.MILLISECONDS); } catch (InterruptedException ignore) { // Ignore } if ( att.getReadLatch()!=null && att.getReadLatch().getCount()> 0) { //we got interrupted, but we haven't received notification from the poller. keycount = 0; }else { //latch countdown has happened keycount = 1; att.resetReadLatch(); } if (readTimeout >= 0 && (keycount == 0)) { timedout = (System.currentTimeMillis() - time) >= readTimeout; } } if (timedout) { throw new SocketTimeoutException(); } } finally { poller.remove(att,SelectionKey.OP_READ); if (timedout && reference.key != null) { poller.cancelKey(reference.key); } reference.key = null; keyReferenceStack.push(reference); } return read;}
  • 根據以上代碼整個讀數據邏輯在一個循環里進行,如果有數據讀到就跳出循環,返回數據。
  • 如果沒有數據,則調用 BlockPoller 的 add() 方法,該方法將封裝的 OP_READ 事件添加到 BlockPoller 的事件隊列里。關于 BlockPoller 我們在后面文章里詳細講解。
  • 然后在調用以前文章介紹的 NioSocketWrapper 中的 CountDownLatch 類型 readLatch 屬性的 await() 方法,使當前線程(一般是tomcat io線程)在 readLatch 上等待。
  • 當前線程在 readLatch 上等待一般有超時時間(讀超時時間),默認不配置為 -1,這時超時時間為 Long.MAX_VALUE 毫秒。

對于 tomcat 數據讀取總結如下:

  • 對于請求行,請求頭和請求體的讀取默認(不開啟異步)都在 tomcat io 線程中進行。

  • 對于請求行和請求頭的讀取是非阻塞讀取,即不阻塞 tomcat io 線程,如果沒有讀取到數據,則由 poll 線程繼續監測下次數據的到來。

  • 對于請求體的讀取是阻塞的讀取,如果發現請求體數據不可讀,那么首先注冊封裝的 OP_READ 事件到 BlockPoller 對象實例的事件隊列里。然后利用 NioSocketWrapper 對象中的 readLatch 來阻塞 tomcat io 線程。

  • 對于 tomcat io 線程阻塞時間為讀超時,默認不配置為 -1,這時超時時間為 Long.MAX_VALUE 毫秒。

  • 如果超時,則拋出 SocketTimeoutException,并取消上面注冊的讀事件。

  • 最后將該事件從 selector 中移除(一般是可讀事件)。

目前先寫到這里,下一篇文章里我們繼續介紹 tomcat 中的響應數據的寫入。

總結

以上是生活随笔為你收集整理的getprivateprofilestring读不到数据_Tomcat NIO(11)请求数据读取的全部內容,希望文章能夠幫你解決所遇到的問題。

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