亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Tomcat源碼分析(二)--連接處理

系統 1944 0
本系列轉載自?http://blog.csdn.net/haitao111313/article/category/1179996?

目標:在這篇文章希望搞明白http請求到tomcat后是怎么由連接器轉交到容器的?

? ? ? 在上一節里已經啟動了一個HttpConnector線程,并且也啟動了固定數量的HttpProcessor線程。HttpConnector用來等待http連接,得到http連接后交給其中的一個HttpProcessor線程來處理。接下里具體看一下HttpConnector是怎么得到連接得,以及HttpProcessor是怎么處理的。當啟動了HttpConnector線程后(在上一節已經知道怎么啟動了),便在它的run方法里面循環等待:

  1. public ? void ?run()?{??
  2. ???? //?Loop?until?we?receive?a?shutdown?command ??
  3. ???? while ?(!stopped)?{??
  4. ???????? //?Accept?the?next?incoming?connection?from?the?server?socket ??
  5. ????????Socket?socket?=? null ;??
  6. ???????? try ?{??
  7. ????????????socket?=?serverSocket.accept();??
  8. ???????????? if ?(connectionTimeout?>? 0 )??
  9. ????????????????socket.setSoTimeout(connectionTimeout);??
  10. ????????????socket.setTcpNoDelay(tcpNoDelay);??
  11. ????????}? catch ?(AccessControlException?ace)?{??
  12. ????????????log( "socket?accept?security?exception" ,?ace);??
  13. ???????????? continue ;??
  14. ????????}? catch ?(IOException?e)?{??
  15. ???????????? try ?{??
  16. ???????????????? //?If?reopening?fails,?exit ??
  17. ???????????????? synchronized ?(threadSync)?{??
  18. ???????????????????? if ?(started?&&?!stopped)??
  19. ????????????????????????log( "accept?error:?" ,?e);??
  20. ???????????????????? if ?(!stopped)?{??
  21. ????????????????????????serverSocket.close();??
  22. ????????????????????????serverSocket?=?open();??
  23. ????????????????????}??
  24. ????????????????}??
  25. ??????????????????
  26. ????????????}? catch ?(IOException?ioe)?{??
  27. ????????????????log( "socket?reopen,?io?problem:?" ,?ioe);??
  28. ???????????????? break ;??
  29. ????????????}? catch ?(KeyStoreException?kse)?{??
  30. ????????????????log( "socket?reopen,?keystore?problem:?" ,?kse);??
  31. ???????????????? break ;??
  32. ????????????}? catch ?(NoSuchAlgorithmException?nsae)?{??
  33. ????????????????log( "socket?reopen,?keystore?algorithm?problem:?" ,?nsae);??
  34. ???????????????? break ;??
  35. ????????????}? catch ?(CertificateException?ce)?{??
  36. ????????????????log( "socket?reopen,?certificate?problem:?" ,?ce);??
  37. ???????????????? break ;??
  38. ????????????}? catch ?(UnrecoverableKeyException?uke)?{??
  39. ????????????????log( "socket?reopen,?unrecoverable?key:?" ,?uke);??
  40. ???????????????? break ;??
  41. ????????????}? catch ?(KeyManagementException?kme)?{??
  42. ????????????????log( "socket?reopen,?key?management?problem:?" ,?kme);??
  43. ???????????????? break ;??
  44. ????????????}??
  45. ??
  46. ???????????? continue ;??
  47. ????????}??
  48. ??
  49. ???????? //?Hand?this?socket?off?to?an?appropriate?processor ??
  50. ????????HttpProcessor?processor?=?createProcessor();??
  51. ???????? if ?(processor?==? null )?{??
  52. ???????????? try ?{??
  53. ????????????????log(sm.getString( "httpConnector.noProcessor" ));??
  54. ????????????????socket.close();??
  55. ????????????}? catch ?(IOException?e)?{??
  56. ????????????????;??
  57. ????????????}??
  58. ???????????? continue ;??
  59. ????????}??
  60. ???????
  61. ????????processor.assign(socket);??
  62. ??
  63. ????}??
  64. ??
  65. ???? //?Notify?the?threadStop()?method?that?we?have?shut?ourselves?down ??
  66. ???
  67. ???? synchronized ?(threadSync)?{??
  68. ????????threadSync.notifyAll();??
  69. ????}??
  70. ??
  71. }??
這里很關鍵的就是socket = serverSocket.accept();和processor.assign(socket); 在循環里面內,serverSocket.accept();負責接收http請求然后賦值給socket,最后交給其中一個processor處理。這里processor并不是等到需要的時候再實例化,而是在HttpConnector初始化的時候已經有了若干個processor,在httpConnector里有這樣一個聲明:

  1. private ?Stack?processors?=? new ?Stack();??
表明httpConnector里面持有一個包含HttpProcessor對象的棧,需要的時候拿出來就是了。看一下createProcessor函數就能比較明白了:

  1. private ?HttpProcessor?createProcessor()?{??
  2. ????? synchronized ?(processors)?{??
  3. ????????? if ?(processors.size()?>? 0 )?{??
  4. ????????????? return ?((HttpProcessor)?processors.pop());? //從processors棧中彈出一個processor ??
  5. ?????????}??
  6. ????????? if ?((maxProcessors?>? 0 )?&&?(curProcessors?<?maxProcessors))?{??
  7. ????????????? return ?(newProcessor());??
  8. ?????????}? else ?{??
  9. ????????????? if ?(maxProcessors?<? 0 )?{??
  10. ????????????????? return ?(newProcessor());??
  11. ?????????????}? else ?{??
  12. ????????????????? return ?( null );??
  13. ?????????????}??
  14. ?????????}??
  15. ?????}??
  16. ??
  17. ?}??

接下來由processor.assign(socket); 記住這個方法是異步的,不需要等待HttpProcessor來處理完成,所以HttpConnector才能不間斷的傳入Http請求,在HttpProcessor里有兩個方法比較重要,這兩個方法協調處理了由HttpConnector傳來的socket:

  1. ? synchronized ? void ?assign(Socket?socket)?{??
  2. ??
  3. ???? //?Wait?for?the?Processor?to?get?the?previous?Socket ??
  4. ???? while ?(available)?{??
  5. ???????? try ?{??
  6. ????????????wait();??
  7. ????????}? catch ?(InterruptedException?e)?{??
  8. ????????}??
  9. ????}??
  10. ??
  11. ???? //?Store?the?newly?available?Socket?and?notify?our?thread ??
  12. ???? this .socket?=?socket;??
  13. ????available?=? true ;??
  14. ????notifyAll();??
  15. ??
  16. ???? if ?((debug?>=? 1 )?&&?(socket?!=? null ))??
  17. ????????log( "?An?incoming?request?is?being?assigned" );??
  18. ??
  19. }??
  20. ??
  21. ??
  22. private ? synchronized ?Socket?await()?{??
  23. ??
  24. ???? //?Wait?for?the?Connector?to?provide?a?new?Socket ??
  25. ???? while ?(!available)?{??
  26. ???????? try ?{??
  27. ????????????wait();??
  28. ????????}? catch ?(InterruptedException?e)?{??
  29. ????????}??
  30. ????}??
  31. ??
  32. ???? //?Notify?the?Connector?that?we?have?received?this?Socket ??
  33. ????Socket?socket?=? this .socket;??
  34. ????available?=? false ;??
  35. ????notifyAll();??
  36. ??
  37. ???? if ?((debug?>=? 1 )?&&?(socket?!=? null ))??
  38. ????????log( "??The?incoming?request?has?been?awaited" );??
  39. ??
  40. ???? return ?(socket);??
  41. ??
  42. }??

看一下HttpProcessor的run方法:

  1. public ? void ?run()?{??
  2. ??
  3. ??????? //?Process?requests?until?we?receive?a?shutdown?signal ??
  4. ??????? while ?(!stopped)?{??
  5. ??
  6. ??????????? //?Wait?for?the?next?socket?to?be?assigned ??
  7. ???????????Socket?socket?=?await();??
  8. ??????????? if ?(socket?==? null )??
  9. ??????????????? continue ;??
  10. ??
  11. ??????????? //?Process?the?request?from?this?socket ??
  12. ??????????? try ?{??
  13. ???????????????process(socket);??
  14. ???????????}? catch ?(Throwable?t)?{??
  15. ???????????????log( "process.invoke" ,?t);??
  16. ???????????}??
  17. ??
  18. ??????????? //?Finish?up?this?request ??
  19. ???????????connector.recycle( this );??
  20. ??
  21. ???????}??
  22. ??
  23. ??????? //?Tell?threadStop()?we?have?shut?ourselves?down?successfully ??
  24. ??????? synchronized ?(threadSync)?{??
  25. ???????????threadSync.notifyAll();??
  26. ???????}??
  27. ??
  28. ???}??

很明顯,在它的run方法一開始便是調用上面的await方法來等待(因為一開始available變量為false),所以HttpProcessor會一直阻塞,直到有線程來喚醒它。當從HttpConnector中調用processor.assign(socket),會把socket傳給此HttpProcessor對象,并設置available為true,調用notifyAll()喚醒該processor線程以處理socket。同時,在await方法中又把available設置成false,因此又回到初始狀態,即可以重新接受socket。

這里處理socket的方法是process(socket),主要作用有兩點,1:解析這個socket,即解析http請求,包括請求方法,請求協議等,以填充request,response對象(是不是很熟悉,在servlet和jsp開發經常用到的request,response對象就是從這里來的)。2:傳入request,response對象給和HttpConnector綁定的容器,讓容器來調用invoke方法進行處理。process方法主要的代碼如下:

  1. private ? void ?process(Socket?socket)?{??
  2. ???????????????????input?=? new ?SocketInputStream(socket.getInputStream(),??
  3. ??????????????????????????????????????????connector.getBufferSize());??
  4. ??????????????????? //解析一下連接的地址,端口什么的 ??
  5. ????????????????????parseConnection(socket);??
  6. ???????????????????? //解析請求頭的第一行,即:方法,協議,uri ??
  7. ????????????????????parseRequest(input,?output);??
  8. ???????????????????? if ?(!request.getRequest().getProtocol()??
  9. ????????????????????????.startsWith( "HTTP/0" ))??
  10. ????????????????????parseHeaders(input); //解析http協議的頭部 ??
  11. ????????????????????..............................................??
  12. ????????????????????connector.getContainer().invoke(request,?response);??
  13. ????????????????????.............................................??
  14. }??
在那些parse××方法里面會對request,response對象進行初始化,然后調用容器的invoke方法進行處理,至此,http請求過來的連接已經完美的轉交給容器處理,容器剩下的問題就是要最終轉交給哪個servlet或者jsp的問題。前面我們知道,一個連接會跟一個容器相連,一個級別大的容器會有一個或者多個子容器,最小的容器是Wrapper,對應一個servlet,在這里我們只要知道請求的路徑決定了最終會選擇哪個wrapper,wrapper最終會調用servlet的。至少一開始提出來的問題已經明白了。這里又有一個問題,在調用invoke方法是有這樣的connector.getContainer的代碼,即通過連接器得到跟它關聯的容器,這個連接器是什么時候跟容器關聯上的? 詳見下篇: Tomcat源碼分析(三)--連接器是如何與容器關聯的?

Tomcat源碼分析(二)--連接處理


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 色综合综合色综合色综合 | 国产大片免费观看中文字幕 | 青青青国产免费线在 | 久久免费精品视频在线观看 | 麻豆成人在线 | 国产精品久久毛片蜜月 | 国产一级视频在线观看 | 亚洲乱码在线视频 | 狼狼色丁香久久婷婷综合五月 | 日韩欧美精品一区二区 | 狠狠色噜狠狠狠狠色综合久 | 免费国产之a视频 | 久久天天躁狠狠躁夜夜呲 | 亚洲狠狠成人综合网 | 幸福宝色多多 | 国产精品网站 夜色 | 中国大陆高清aⅴ毛片 | 亚洲国产欧美国产第一区二区三区 | 99在线在线视频免费视频观看 | 99热在线这里只有精品 | 韩国办公室激情 | 亚洲精品一二三四区 | 久久久久久久久毛片精品 | 在线欧洲成人免费视频 | 欧美精品v国产精品v | 九九九九热精品免费视频 | 一级免费看片 | 天天躁狠狠躁狠狠躁夜夜躁 | 一区二区视频在线观看免费的 | 中文字幕精品视频在线观 | 久久国产精品一国产精品金尊 | 天天爽夜夜爽夜夜爽精品视频 | 动漫精品一区二区 | 天天干天天夜 | 亚洲一区二区三区久久精品 | 91久久综合 | 欧美日韩免费在线视频 | 欧美最猛的24k毛片视频 | 色综合五月激情综合色一区 | 瑟瑟视频在线观看 | 国产精品午夜波多野结衣性色 |