Ã¥ÂÂè¨Â
å ³äºÂç½Âç»Âç¸堳çÂÂæÂÂç« å·²ç»ÂÃ¥ÂÂè¿Âå¾Âå¤ÂäºÂ:
[1]ãÂÂ计ç®Âæºç½Âç»Âå¼Â论ãÂÂ
[2]ãÂÂ计ç®Âæºç½Âç»Âå®Âå ¨å¼Â论ãÂÂ
[3]ãÂÂNIO å¦习ç¬Âè®°(ä¸Â)Ã¥ÂÂéÂÂãÂÂ
[4]ãÂÂSocketç®Âä»ÂÃ¥ÂÂI/Oå¤Âè·¯å¤Âç¨ãÂÂ
[5]ãÂÂNIO å¦习ç¬Âè®°(äºÂ)ç¸è¯Âç¯ÂãÂÂ
[6]ãÂÂNIOå¦习ç¬Âè®°(ä¸Â) çÂÂ欢ç¯ÂãÂÂ
[7]ãÂÂNettyå¦习ç¬Âè®°(ä¸Â)Ã¥ÂÂéÂÂç¯ÂãÂÂ
[8]ãÂÂHTTP/2.0çÂÂäºÂè¿Âå¶æ¯ä»Âä¹Â?ãÂÂ
[9] ãÂÂæÂÂ们æÂ¥èÂÂèÂÂHTTPSå§ãÂÂ
[10] TCP å¦习ç¬Âè®°(ä¸Â) å¯é 传è¾Â
[11] HTTPå¦习ç¬Âè®°(ä¸Â) HTTP/2
[12] TCPå¦习ç¬Âè®°(äºÂ) ç¸è¯Âç¯Â
[13] HTTPÃ¥ÂÂè®®å¦习ç¬Âè®°(ä¸Â) Ã¥ÂÂéÂÂç¯Â
[14] TCPå¦习ç¬Âè®°(ä¸Â) Ã¥ÂÂéÂÂç¯Â
æ¬系åÂÂæÂÂç®Âç³ åÂÂè¿ÂäºÂæÂÂç« ï¼Â使ç¨JavaÃ¥ÂÂä¸Â个ç®ÂÃ¥ÂÂçÂÂHTTP/HTTPSæÂÂå¡å¨ï¼ÂæÂÂçÂÂé¢Â设æ¯å¸ÂæÂÂ读è 诸åÂÂå·²ç»ÂçÂÂè¿Âä¸Âé¢çÂÂæÂÂç« äºÂï¼Âä½Âæ¯æ°äºÂæ°ä¸Âé¢大è´æÂÂÃ¥ÂÂÃ¥ÂÂç¯ÂäºÂï¼Âå¸Âæ 读è 诸åÂÂå·²é ä¸Âé¢çÂÂæÂÂç« ï¼Âæ³æÂ¥æÂÂäºÂ奢æÂÂãÂÂé£è¿ÂéÂÂ大è´çÂÂçÂÂçÂÂè¿ÂäºÂæÂÂç« çÂÂç»ÂæÂÂï¼Â并ç»Âåºä¸Â个é 读æ¬ç¯ÂçÂÂæÂÂå°ÂçÂ¥è¯Âç¹ãÂÂ让æÂÂ们ä»Âç½Âç»ÂéÂÂä¿¡å¼Âå§Â说起ï¼Âå¦ÂæÂÂéÂÂä¿¡çÂÂÃ¥ÂÂæ¹ä¸Âæ¯é¢对é¢ï¼Âé£ä¹Â交æµÂå°±è¦ÂÃ¥ÂÂå©äºÂè½½ä½Âï¼ÂæÂÂæ³起å°Âæ¶åÂÂç»Â常çÂÂçÂÂæ¦侠çµ影ï¼Âå§åºÂå°Âæ æÂ¥ç»Âå¨信鸽çÂÂè ¿ä¸Âï¼Âä½Âæ¯è¿Âæ ·ä¼ éÂÂæ æÂ¥çÂÂæ¹å¼Âï¼Âæ æ¥就æÂÂ被篡æ¹ãÂÂ丢失ãÂÂæªè·çÂÂé£Âé©ãÂÂ篡æ¹ãÂÂ丢失ãÂÂæªè·ï¼Âè¿Âä¹Âæ¯éÂÂä¿¡è¦Âé¢临çÂÂä¸Â个é®é¢ÂãÂÂéÂÂçÂÂæ¶代çÂÂÃ¥ÂÂå±Âï¼Âè¶ÂæÂ¥è¶Âå¿«çÂÂ交äºÂä¿¡æ¯åÂÂå¾Âè¶ÂæÂ¥è¶Âè¿«åÂÂï¼Â计ç®Âæº帮å©æÂÂ们å®ÂæÂÂä»»å¡ä¹ÂÃ¥ÂÂï¼ÂæÂÂ们å¸ÂæÂÂä¹Âå¨计ç®Âæºä¸Âå®ÂæÂÂä¿¡æ¯çÂÂ交æ¢ï¼Âé£ä¹Âè¦Âå®ÂæÂÂä¿¡æ¯çÂÂ交æ¢ï¼Â两å°计ç®Âæºå¿忠è¦ÂæÂÂä¿¡éÂÂï¼Âä¿¡éÂÂæ¯传è¾Âä¿¡æ¯çÂÂéÂÂéÂÂï¼Âä½Âæ¯æÂÂäºÂéÂÂéÂÂè¿Âä¸Âå¤Âï¼ÂéÂÂä¿¡çÂÂÃ¥ÂÂæ¹è¿ÂéÂÂè¦Âå½¼æ¤çÂ¥éÂÂå°åÂÂï¼ÂæÂÂäºÂå°åÂÂè¿Âä¸Âå¤Âï¼ÂæÂÂ们è¿Âè¦Âé¿å Âä¿¡æ¯çÂÂæªè·ãÂÂ丢失ãÂÂ篡æ¹ãÂÂ
å¨éÂÂä¿¡çÂÂæ¶åÂÂï¼ÂéÂÂä¿¡çÂÂÃ¥ÂÂæ¹æ¯æÂÂç¡®çÂÂï¼Âä¹Âå°±æ¯说æÂÂçÂ¥éÂÂæÂÂè¦ÂÃ¥ÂÂè°ÂéÂÂä¿¡ï¼Â以ä¸Âå°±æ¦Âæ¬äºÂ两å°计ç®ÂæºéÂÂä¿¡è¦Âé¢临çÂÂé®é¢Âï¼Âé¢对è¿Âä¹Âå¤Âé®é¢Âï¼Â计ç®ÂæºäºÂèÂÂç½ÂçÂÂå Â驱们ï¼ÂéÂÂæ©äºÂÃ¥ÂÂå±Âæ¥解å³é®é¢Âï¼Â两å°计ç®Âæºä¹Âé´çÂÂä¿¡éÂÂ被åÂÂå°ç©çÂÂå±Âï¼Âä¿¡æ¯æÂÂç»Âè¦Â转åÂÂ为信å·ï¼ÂèÂÂç©çÂÂå±Âå°±è´Â责传è¾Âä¿¡å·ãÂÂÃ¥ÂÂ纯çÂÂ0Ã¥ÂÂ1没æÂÂä»»ä½ÂæÂÂä¹Âï¼Âå¿ é¡»è§Âå®Â解读æ¹å¼Âï¼Âå¤Âå°Â个çµ信å·ç®Âä¸Âç»Âï¼ æ¯Â个信å·ä½ÂæÂÂä½ÂæÂÂä¹Âï¼ å¦ÂæÂÂæÂÂ们åªæÂÂ两å°计ç®Âæºï¼Âä¿¡å·éÂÂç»Âæ¯æÂÂç¡®çÂÂï¼ÂæÂÂæ©çÂÂç½Âç»Âæ¯ç«+çµè¯Â线ï¼Âè¿Âä¸Âæ¡çµè¯Â线ãÂÂçÂÂ论ä¸ÂÃ¥ÂÂæ¹åªè¦Âå®ÂæÂÂæ¨å·ï¼ÂÃ¥ÂÂæ¹就è½è¿Âè¡ÂéÂÂä¿¡ãÂÂè¿Â个è¿Âç¨Âè·Â两个人æÂÂçµè¯Â没ä»Âä¹Âåºå«ãÂÂ
è¿Âç§Âé¾路æÂÂ们称ä¹Â为ç¹对ç¹é¾路ãÂÂç¹对ç¹é¾路çÂÂæÂÂç¹æ¯ç®ÂÃ¥ÂÂï¼Â缺ç¹æ¯æ¯Âå 堥ä¸Âå°计ç®Âæºï¼Âå°±è¦Âç»ÂçµèÂÂæ°é Âç½®ä¸Â个ç«ï¼Âå¦ÂæÂÂæÂÂæÂÂå¤Âå°çµèÂÂï¼Âè¿ÂäºÂçµèÂÂéÂÂè¦ÂäºÂç¸è¿ÂæÂ¥ï¼Âå°±éÂÂè¦Âæ¯Â个çµèÂÂçÂÂç«è¿ÂæÂ¥å°ä¸Âèµ·ï¼Âè¿Â带æÂ¥çÂÂæÂÂæ¬å¾Âé«Âï¼Â管çÂÂæÂÂæ¬ä¹ÂéÂÂ常éÂÂï¼Âè¿Âç§Âè¿ÂæÂ¥æ¹å¼Â被称为堨ç½Âç¶æÂÂæÂÂ(Full Mesh)ç½Âç»ÂãÂÂè¿Âç§Âè¿ÂæÂ¥æ¹å¼Âä¹Âä¸Âæ¯ä¸Âæ æ¯å¤Âï¼Âä¼Âç¹æ¯å¯é æ§é«Âï¼Âç½Âç»Âä¸Âé¨åÂÂé¾æÂ¥åºç°æ éÂÂä¸Âä¼Âå½±åÂÂå°æ´个ç½Âç»ÂãÂÂä½ÂæÂÂæ¬é«Âï¼Âç»´æ¤å°é¾æ¯çÂÂçÂÂæ¿åÂÂä¸Âä½ÂãÂÂ
为äºÂéÂÂä½ÂæÂÂæ¬ï¼Â人们æ³å°äºÂå¦å¤Âä¸Âç§Âè¿ÂæÂ¥æ¹å¼Âï¼Âä¹Âå°±æ¯æÂÂæÂÂçÂÂçµèÂÂåªéÂÂè¦Âè¿ÂæÂ¥ä¸Â个ç«ï¼Âç¶åÂÂæÂÂæÂÂç«è¿ÂæÂ¥å°åÂÂä¸Âæ¡ç½Â线ä¸Â(å«æ»线)ãÂÂæÂÂ们称è¿Âç§Âè¿ÂæÂ¥æ¹å¼Â为æ»线ç½Âç»ÂãÂÂè¿Âç§Âæ¹å¼ÂçÂÂç¡®éÂÂä½ÂäºÂç»Âç½ÂçÂÂæÂÂæ¬ï¼Âä½Âæ¯使ç¨æÂÂæΫä¸ÂÃ¥ÂÂäºÂãÂÂå¦ÂæÂÂä¸Âå¾ä¸ÂçÂÂAæ³ç»ÂBÃ¥ÂÂéÂÂæ°æ®ï¼Âå¯以å¯å¨èª己çÂÂç«åÂÂéÂÂï¼Âé£ä¹Âå¦ÂæÂÂæ¤æ¶CÃ¥ÂÂDÃ¥ÂÂæ°æ®ï¼Âé£ä¹Âå°±ä¼Âå½¢æÂÂå¹²æ°ï¼ÂæÂÂç»Âè°ÂçÂÂæ°æ®ä¹ÂÃ¥ÂÂä¸ÂåºæÂ¥ãÂÂ为äºÂ解å³è¿Â个é®é¢Âï¼Â人们è§Âå®Âï¼Âå¦ÂæÂÂæ³åÂÂæ°æ®ï¼Âå¿ é¡»å Âè¯Âç¨èª己çÂÂç«å¬ä¸Âä¸Âç½Â线ä¸ÂæÂÂ没æÂÂå ¶ä»ÂçµèÂÂæ£å¨éÂÂä¿¡ãÂÂå¦ÂæÂÂæÂÂï¼Âå°±èªè§ÂçÂÂå¾ ä¸Â段æ¶é´ï¼Âç¶åÂÂÃ¥ÂÂæ£ÂæÂ¥ãÂÂè¿Âå¥Âæºå¶åÂÂæÂ¥æ¼ÂÃ¥ÂÂäºÂæÂÂ载波侦å¬å¤Â路访é®/碰æÂÂæ£ÂæµÂ(CSMA/CD)æºå¶ãÂÂæÂÂç§Â书ä¸Âé½ä¼Âå°Âè¿Â个CSMA/CD(æÂÂå·²ç»Âç»Âå¿Âè®°äºÂ)ãÂÂ
解å³äºÂå²çªÂé®é¢Âï¼Âæ»线ç½Âç»Âå°±è½工ä½ÂÃ¥ÂÂï¼Âå½Âç¶æ¯ä¸Âè½çÂÂ! æÂÂ们å¨ç¾åÂÂ讲çÂÂç¹对ç¹两边åÂÂæÂÂä¸Âå°çµèÂÂï¼Âæ¶æ¿åÂÂæ¹éÂÂ常æÂÂç¡®ï¼Âä¸ÂéÂÂè¦Âé¢Âå¤Âä¿¡æ¯ãÂÂé£ä¹Âå¨æ»线ç½Âç»Âä¸Âï¼ÂæÂÂæÂÂçµèÂÂ報享ä¸Âæ¡çÂ懬Âï¼Âå¯以åÂÂæ¶æÂ¥æ¶ç½Âç»Âä¸ÂçÂÂå ¨é¨信å·ãÂÂé£大家å¦Âä½Âç¡®å®Âæ°æ®æ¯å¦Âä½ÂÃ¥ÂÂç»Âèª己çÂÂå¢ï¼Â为äºÂ解å³è¿Â个é®é¢Âï¼Â人们åÂÂæÂÂäºÂæ°æ®帧è¿Â个æ¦Â念ãÂÂ帧æ¯åÂÂéÂÂæ°æ®çÂÂæÂÂå°ÂÃ¥ÂÂä½Âï¼Âå½Âæ¶æÂÂå¾Âå¤Âé¾路å±ÂÃ¥ÂÂè®®ï¼Â以太ç½Âåªæ¯åÂÂé¢æ¶ÂÃ¥ÂÂçÂÂä¸Âç§ÂãÂÂä½Âæ¯ä¸ÂÃ¥ÂÂçÂÂ帧ç»ÂæÂÂé½æ¯大åÂÂå°Âå¼Âï¼Âæ ¸å¿Âé½å å«ç®æ Âå°åÂÂãÂÂæºÂå°åÂÂÃ¥ÂÂæ°æ®ä¸Âé¨åÂÂï¼Âè¿Âä¹Âæ¯åÂÂå¯Âä¿¡ä¸Âæ ·ï¼Âä¿¡å°Âæ¯æº带äºÂÃ¥ÂÂéÂÂ人çÂÂå°åÂÂãÂÂæ¶信人çÂÂå°åÂÂãÂÂä¿¡å 容ãÂÂ
è¿ÂéÂÂé¦Â次åºç°äºÂå°åÂÂè¿Â个æ¦Â念ãÂÂæ£æ¯å 为æ»线ç½Â线ä¸ÂæÂÂæÂÂ设å¤Â報享æ»线ï¼ÂæÂÂ以éÂÂè¦ÂéÂÂè¿Âå¼Âå ¥å°åÂÂçÂÂæ¦Â念æÂ¥åºåÂÂä¸ÂÃ¥ÂÂçÂÂ设å¤ÂãÂÂ对äºÂ以太ç½Âï¼Âè¿Â个å°åÂÂå°±æ¯æÂÂ们常说çÂÂMACå°åÂÂãÂÂè¿Â个æ¶åÂÂç«已ç»ÂÃ¥ÂÂæÂÂäºÂæÂÂ们ç°å¨常说çÂÂç½Âå¡äºÂãÂÂ以太ç½Âè§Âå®ÂMACå°åÂÂå 6个åÂÂèÂÂï¼Âä¹Âå°±æ¯åÂÂé¢说çÂÂ48ä½ÂãÂÂ
æÂÂæÂÂÃ¥ÂÂåºçÂÂå é½带çÂÂç®æ ÂçµèÂÂçÂÂMACå°åÂÂãÂÂç½Âç»Âä¸ÂæÂÂæÂÂ设å¤Âæ¶å°æ°æ®åÂÂä¼Âèªè§Âæ¯Âè¾Âç®æ Âå°åÂÂæ¯ä¸Âæ¯èª己ï¼Âå¦ÂæÂÂä¸Âæ¯就丢å¼Âï¼Âæ¯çÂÂï¼Â你没æÂÂåŽÂÂï¼Âå ¨åÂÂ大家èªè§ÂãÂÂè¿Â样就解å³äºÂä¸Âé¢æÂÂ们æÂÂåºçÂÂé®é¢ÂãÂÂ
å¼Âå ¥å°åÂÂçÂÂæ¦Â念ï¼Âä¹Â就产çÂÂäºÂæ°çÂÂé®é¢Â-å¦Âä½Âç»Â计ç®Âæº设置MACå°åÂÂå¢@ä¸ÂÃ¥ÂÂçÂÂç½Âç»ÂæÂÂä¸ÂÃ¥ÂÂçÂÂå¤ÂçÂÂæ¹å¼ÂãÂÂ
æ¾ç»ÂæÂÂä¸Âç§Âå«ARCNETçÂÂç½Âç»ÂÃ¥ÂÂè®®ï¼Âå®ÂçÂÂMACå°åÂÂåªæÂÂ1个åÂÂèÂÂ(8ä½Â)ï¼ÂéÂÂè¦Âç½Âç»Â管çÂÂÃ¥ÂÂéÂÂè¿Âç½Âå¡ä¸ÂçÂÂæ¨å¨å¼Âå ³æÂÂ工设置å¼Â堳设置ãÂÂ好å¨å½Âå¹´è½è¿Âç½ÂçÂÂ设å¤Âå¾Âå°Âï¼Â8ä½Âå°åÂÂå¯以æ¯æÂÂæÂÂå¤Â256å°设å¤Âè¿Âç½Âï¼Âä¹Âå¤Âç¨äºÂãÂÂ
以太ç½Âè§Âå®Âå¨ç½Âå¡åºåÂÂçÂÂæ¶åÂÂå°±å¾ÂÃ¥ÂÂé Â48ä½ÂMACå°åÂÂï¼Âå ¨çÂÂå¯ä¸ÂãÂÂ
éÂÂçÂÂæ»线ç½Âç»ÂçÂÂæ®åÂÂï¼Âè¶ÂæÂ¥è¶Âå¤ÂçÂÂ大堬å¸æÂÂè æ¯大å¦å¼Âå§Â使ç¨ç½Âç»Âè¿ÂæÂ¥å®Â们çÂÂ设å¤ÂãÂÂ为äºÂæ¹便传è¾Âæ°æ®ï¼Â人们è¿ÂÃ¥ÂÂæÂÂäºÂç½Âæ¡¥ï¼ÂæÂÂ们å¯以å°Âç½Âæ¡¥æ³象æÂÂ裠æÂÂå¤Â个ç½Âå¡çÂÂ设å¤Âï¼Âæ¯Â个ç½Âå¡è¿ÂæÂ¥ä¸Â个æ»线ç½Âç»ÂãÂÂç½Âæ¡¥å¯ä¸ÂçÂÂä½Âç¨就æ¯æÂÂä¸Â个ç½Âå¡æ¶å°çÂÂå 容åÂÂ样转åÂÂå°å¦ä¸Âå¼ ç½Âå¡æÂÂå¨çÂÂç½Âç»ÂãÂÂ
è¿Âæ ·ç½Âç»ÂçÂÂè§Â模è¶ÂæÂ¥è¶Â大ï¼Âè¿Âç½ÂçÂÂ设å¤Âè¶ÂæÂ¥è¶Âå¤Âï¼ÂéÂÂä¿¡å²çªÂçÂÂé¢ÂçÂÂ页è¶ÂæÂ¥è¶Âé«ÂãÂÂæÂÂç»ÂçÂÂç»ÂæÂÂå°±æ¯æ°æ®传è¾ÂçÂÂè¶ÂæÂ¥è¶Âä½Â(å 为åªè¦ÂæÂÂä¸Â个人å¨åÂÂæ°æ®ï¼Âå ¶ä»ÂæÂÂæÂÂ人é½å¾ÂçÂÂå¾ )ãÂÂä½Âå°±è¿Âæ ·ï¼Â人们对äºÂèÂÂäºÂéÂÂçÂÂè¦Âæ±Âè¿Âæ¯没被满足ãÂÂé¤äºÂå ¬å¸æÂÂè ç»Âç»Âå é¨çÂÂç½Âç»Âï¼Â人们è¿Âæ³æÂÂä¸ÂÃ¥ÂÂÃ¥ÂÂå¸ÂçÂÂ设å¤ÂÃ¥ÂÂç½Âç»Âé½è¿Âèµ·æÂ¥ï¼Âè¿Âå°±éÂÂè¦Âç¨å°é¿éÂÂçµè¯Â线ãÂÂ
Ã¥ÂÂé¢æÂÂ们说è¿Âç½Âæ¡¥æ¯ä¸Âç§Âæ èÂÂ转åÂÂ设å¤Âï¼Âå®ÂçÂÂæ èÂÂä¸Âä» ä½Âç°å¨ä¸Âå ³å¿Âæ°æ®å 容æ¹é¢ï¼Âè¿Âä½Âç°å¨尽èª己æÂÂ大è½åÂÂ转åÂÂãÂÂå¦ÂæÂÂæ¯ç¸åÂÂå±ÂÃ¥ÂÂç½Âï¼Â两边çÂÂç½ÂéÂÂç¸è¿Âï¼Âé£ä¸Âä¼ÂæÂÂä»Âä¹Âé®é¢ÂãÂÂé£å¦ÂæÂÂä¸Âè¾¹æ¯å±ÂÃ¥ÂÂç½Âï¼Âä¸Âè¾¹æ¯é¿éÂÂçµè¯Â线ï¼Âé£ä¹ÂæÂ¥èªå±ÂÃ¥ÂÂç½ÂçÂÂ广æÂÂæ°æ®ä¼ÂæÂÂçµè¯Â线æ¤çÂÂï¼Â大家è°Âä¹Âå«æ³ç©ãÂÂ
æ¢ç¶åºç°äºÂè¿Âæ ·çÂÂé®é¢Âï¼ÂæÂÂä¹Âå°±éÂÂè¦Â对ç½Âæ¡¥è¿Âè¡Âæ¹é ï¼ÂæÂÂ们å¸ÂæÂÂé£个ç½Âæ¡¥æºè½ä¸Âç¹ãÂÂ让å®Âå¯以å¦习ä¸ÂÃ¥ÂÂç½Âç»ÂæÂÂæÂÂ设å¤ÂçÂÂMACå°åÂÂãÂÂå½ÂæÂÂæ°æ®è¦Â转åÂÂçÂÂæ¶åÂÂï¼Âå®Âå¯以根æ®ç®æ Âå°åÂÂå¤æÂÂåºÂ该转åÂÂå°åª个ç½Âå¡ï¼Âä»ÂèÂÂÃ¥ÂÂå°Â广æÂÂæ°éÂÂãÂÂ
ä½Âæ¯å 为以太ç½ÂçÂÂMACå°åÂÂæ¯å¨åºåÂÂçÂÂæ¶åÂÂæÂÂå®ÂçÂÂï¼Âé£ä¹Â就没æÂÂÃ¥ÂÂæ³Âç¡®å®ÂæÂÂ个æ»线ç½Âç»Âä¸ÂæÂÂæÂÂçÂÂAMCå°åÂÂï¼Âåªè½éÂÂè¿Â广æÂÂæÂ¥å¦习ï¼Âä¹Âåªè½å¨ç½Â桥设å¤Âä¿ÂÃ¥ÂÂå ¨é¨MACå°åÂÂï¼ÂèÂÂä¸Âè¿Âè¦ÂÃ¥ÂÂæ¶æ´æ°ãÂÂé¤æ¤ä¹Âå¤Âï¼Âç½Âæ¡¥æ¬身åª转åÂÂï¼ÂçÂÂ论ä¸Âä¹Âä¸ÂéÂÂè¦ÂMACå°åÂÂãÂÂæÂÂ以ç½Âç»Âå çÂÂ计ç®ÂæºçÂ¥éÂÂæ°æ®æ¯ç»Âè¿ÂäºÂå 个ç½Â桥转åÂÂï¼Âå¦ÂæÂÂåºäºÂé®é¢Âï¼Âä¹Âä¸ÂçÂ¥éÂÂå¨åª个ç¯èÂÂåºäºÂé®é¢ÂãÂÂ
æÂÂç»ÂIETF(Internet Enginering Task Force)ç»ÂåºäºÂ解å³æ¹桠ï¼Âä¹Âå°±æ¯åÂÂå ä¸Âå±Âï¼Âä¹Âå°±æ¯å¨以太ç½Âä¹Âä¸Âå¼Âå ¥äºÂç½Âç»Âå±Â(ä¹Âå°±æ¯IPå±Â)ã 就æ¯å¼Âå ¥é»è¾Âå°åÂÂï¼Âè¿Âä¹Âå°±æ¯IPå°åÂÂï¼ÂèÂÂä¸Âè§Âå¾Â32ä½Âå·®ä¸Âå¤Âå¤Âç¨äºÂï¼ÂçÂÂè³é½没èÂÂèÂÂMACå°åÂÂé½æ¯48ä½ÂãÂÂéÂÂè¿ÂIPå°åÂÂæÂÂ们就å¯以å°Âç½Âç»ÂÃ¥ÂÂÃ¥ÂÂæÂÂ许å¤Â个åÂÂç½Âï¼Âæ ¹æ®é»è¾Âå°åÂÂï¼ÂæÂÂ们就è½çÂ¥éÂÂè¦Â转åÂÂç»Âåª个ç½Âå¡äºÂï¼Âä»ÂèÂÂÃ¥ÂÂå°Â广æÂÂæ°éÂÂãÂÂæÂÂ以ï¼Âæ¯Â个设å¤Âæ³è¦Âå 堥ä¸Â个ç½Âç»Âé½éÂÂè¦Â被åÂÂé Âä¸Â个IPå°åÂÂï¼ÂéÂÂä¿¡çÂÂÃ¥ÂÂæ¹使ç¨IPå°åÂÂè¿Âè¡ÂéÂÂä¿¡ãÂÂIPå°åÂÂæ¯管çÂÂÃ¥ÂÂæÂÂéÂÂæÂÂå®ÂçÂÂï¼Âå¯以根æ®åÂÂç¼ÂèÂÂÃ¥ÂÂãÂÂæÂÂ以åÂÂæÂ¥çÂÂç½Âæ¡¥ï¼Âç°å¨åÂÂæÂÂäºÂè·¯ç±å¨ï¼Âä¸ÂéÂÂè¦Âä¿ÂÃ¥ÂÂç½Âç»Âä¸ÂæÂÂæÂÂçÂÂMACå°åÂÂï¼Âåªè¦Âä¿ÂÃ¥ÂÂç½Âç»ÂÃ¥ÂÂç¼Âå°±è½è¿Âè¡Â转åÂÂãÂÂ
é£ä¹Â请é®ï¼Âå¦Âä½Âæ ¹æ®é»è¾Âå°åÂÂå¾Âå°ç®æ ÂçÂÂmacå°åÂÂå¢@è¿Âä¹Âå°±æ¯ARPÃ¥ÂÂè®®ãÂÂæ¯Âå½ÂçµèÂÂå¨éÂÂä¿¡ä¹ÂÃ¥ÂÂä¼Âå Âå¨ç½Âç»Âä¸ÂÃ¥ÂÂä¸Â个广æÂÂ(è¿Â个广æÂÂä¸Âä¼Â被转åÂÂå°堶ä»Âç½Âç»Â)ï¼ é®è°ÂçÂÂIPå°åÂÂæ¯æÂÂæÂÂï¼Âè¿Â个æ¶åÂÂ对åºÂçÂÂçµèÂÂå°±ä¼ÂÃ¥ÂÂå¤Âï¼Âæ¯æÂÂï¼ÂæÂÂçÂÂMACå°åÂÂæ¯æÂÂæÂÂæÂÂãÂÂÃ¥ÂÂéÂÂæ¹就å½Âæ¿å°äºÂæÂ¥æ¶æ¹çÂÂMACå°åÂÂï¼Âè¿ÂèÂÂå®ÂæÂÂéÂÂä¿¡ãÂÂ
å¦ÂæÂÂç®æ ÂçµèÂÂå¨å¦ä¸Â个ç½Âç»Âï¼Âè¿Â个æ¶åÂÂÃ¥ÂÂéÂÂæ¹就ä¼Âå¨èª己çÂÂç½Âç»ÂéÂÂ广æÂÂ说æÂ¥æÂÂç½Âå ³ip设å¤ÂçÂÂæ¯è°Â(æÂÂ们åÂÂ设å®ÂçÂÂé»Â认ç½Âå ³IPæ¯192.168.1.1)ï¼Âç½Â堳就ä¼ÂÃ¥ÂÂå¤Âèª己çÂÂMACãÂÂç¶åÂÂï¼ÂÃ¥ÂÂéÂÂæ¹就ä¼ÂéÂÂè¿Âç½Âå ³çÂÂMACå°åÂÂç»Âç½Âå ³åÂÂéÂÂä¸Âæ¡IPæÂ¥æÂÂï¼ÂæÂ¥æÂÂçÂÂç®æ ÂIPå°±æ¯æÂ¥æ¶æ¹çÂÂIPå°åÂÂï¼ÂæÂ¥æºÂIPèªç¶ä¹Âå°±æ¯åÂÂéÂÂæ¹çÂÂIPå°åÂÂãÂÂç½Âå ³æ¯两个åÂÂç½ÂçÂÂæ¡¥æ¢ÂãÂÂ
é£å¦ÂæÂÂä¸Âå¨ä¸Â个ç½Âç»Âå¢ï¼ÂæÂÂ们æ¥举ä¾Â讲述è¿Â个éÂÂä¿¡è¿Âç¨Âï¼ÂÃ¥ÂÂ设H1æ³åÂÂH2Ã¥ÂÂéÂÂæ°æ®ï¼ÂH1å¨ä¸ÂçÂ¥éÂÂH2å¨ä¸Âå¨ä¸Â个ç½Âç»ÂéÂÂé¢ï¼Âé¦Âå Âå¨èª己æÂÂå¨ç½Âç»ÂéÂÂ广æÂÂï¼Âè°ÂçÂÂIPæ¯æÂÂæÂÂæÂÂï¼Â没人åÂÂå¤Âä¹ÂÃ¥ÂÂï¼Âå°±çÂ¥éÂÂH2Ã¥ÂÂèª己ä¸Âå¨ä¸Â个ç½Âç»ÂäºÂï¼Âè¿Â个æ¶åÂÂä»Âå°±ä¼ÂéÂÂè¿ÂARPÃ¥ÂÂ议解åºæÂ¥ç½Âå ³çÂÂmacå°åÂÂï¼Âç¶åÂÂç»Âç½Âå ³çÂÂmacå°åÂÂÃ¥ÂÂéÂÂäºÂä¸Â个æÂ¥æÂÂï¼ÂæÂ¥æÂÂçÂÂç®æ Âipæ¯h2çÂÂipï¼ÂæºÂipå°åÂÂæ¯H1çÂÂipå°åÂÂï¼Âè·¯ç±å¨æ¶å°è¿Â个æÂ¥æÂÂä¹ÂÃ¥ÂÂï¼Âæ ¹æ®ç®æ Âå°åÂÂç¡®å®Âç®æ Âipå¨åªä¸Â个åÂÂç½Âä¸Âé¢ï¼Â转åÂÂç»Â对åºÂçÂÂè·¯ç±å¨R2ï¼Âè·¯ç±å¨R1ä¿ÂÃ¥ÂÂäºÂH2æÂÂå¨ç½Âç»ÂçÂÂÃ¥ÂÂç¼Âä¸Âï¼Âç¶åÂÂç±路ç±å¨R2转åÂÂç»ÂH2, å¦Âæ¤就å®ÂæÂÂäºÂéÂÂä¿¡è¿Âç¨Âï¼Â
æ´个è¿Âç¨Âï¼ÂH1Ã¥ÂÂR1é½ä¸ÂéÂÂè¦ÂçÂ¥éÂÂH2çÂÂMACå°åÂÂï¼Âä½ÂæÂÂæÂÂèÂÂç¹忠须çÂ¥éÂÂç¸临èÂÂç¹çÂÂMACå°åÂÂï¼Âä¹Âå«ä¸Âä¸Âè·³ï¼ÂãÂÂæÂÂ以说ï¼Âå°ç°å¨为æ¢ï¼ÂåªæÂÂæ¯å¼Âå ¥äºÂIPå±Âï¼Âå®Âé éÂÂä¿¡è¿Âæ¯ä¾ÂèµÂMACå°åÂÂãÂÂå¨IPç½Âç»Âä¸Âï¼Âå¦ÂæÂÂ模æ¿å¨åÂÂä¸Â个ç½Âç»Âï¼ÂÃ¥ÂÂéÂÂè¿Â广æÂÂè¿Âè¡ÂéÂÂä¿¡; å¦åÂÂï¼ÂÃ¥ÂÂéÂÂè¿Âç½Â堳转åÂÂãÂÂå 为æÂÂ广æÂÂçÂÂÃ¥ÂÂå¨ï¼ÂæÂÂ以ç½ÂéÂÂè¿Âæ¯ä¼ÂÃ¥ÂÂå°影åÂÂï¼Âè¿Âæ¶æ¯Â个å±ÂÃ¥ÂÂç½Âä¹Âå«å²çªÂÃ¥ÂÂãÂÂå 为IPç½Âç»Âå¼Âå ¥äºÂè·¯ç±å¨ï¼ÂæÂÂ以è·ÂÃ¥ÂÂæÂ¥çÂÂæ»线ç½Âç»Âç¸æ¯Âï¼Âå²çªÂÃ¥ÂÂÃ¥ÂÂå°ÂäºÂï¼Â广æÂÂÃ¥ÂÂå°ÂäºÂï¼Âç½ÂéÂÂæÂÂé«ÂäºÂãÂÂä½Âæ¯æÂÂ们è¿Âå¸ÂæÂÂç½ÂéÂÂæ´快ï¼ÂäºÂæ¯æÂÂ们åÂÂæÂÂäºÂ交æ¢æºï¼Â交æ¢æºä¹Âæ¯ä¸Âç§Âå±ÂÃ¥ÂÂç½Â设å¤Âï¼ÂÃ¥ÂÂè½åÂÂÃ¥ÂÂé¢说çÂÂç½Â桥类似ï¼Âä½Âæ¯交æ¢æºå¯以è¿Âä¸ÂæÂ¥åÂÂå°Â广æÂÂçÂÂæ°éÂÂãÂÂ
声æÂÂå°è¿ÂéÂÂ为æ¢@åºæ¬å¼Âç¨çÂÂæ¯åÂÂèÂÂèµÂæÂÂ[1], æÂ¥èªçÂ¥ä¹Âä½Âè æ¶ÂÃ¥ÂÂãÂÂä¸Âé¢åºæ¬为æÂÂçÂÂÃ¥ÂÂÃ¥ÂÂãÂÂ
ä½Âæ¯ï¼Â交æ¢æºå¯以è¿Âä¸ÂæÂ¥åÂÂå°Â广æÂÂçÂÂæ°éÂÂãÂÂ以ä¸Âå¾为ä¾ÂãÂÂå¦ÂæÂÂAæ³ç»ÂCÃ¥ÂÂéÂÂæ°æ®ï¼Âå®Âä¼Âå ÂéÂÂè¿ÂARP广æÂÂæ¥询CçÂÂMACå°åÂÂãÂÂè¿Âä¸ÂæÂ¥æ¯å Âä¸ÂäºÂçÂÂãÂÂä½Âæ¯ï¼Âè¿Âä¸ÂæÂ¥ä¹Âä¼Â被交æ¢æºçÂÂå¬/å¦习å°ï¼ÂæÂÂ以交æ¢æºä¼Âå°ÂCè¿ÂæÂ¥çÂÂç½Âå£è·ÂCçÂÂMACå°åÂÂç»Âå®Âå°ä¸Âèµ·ï¼ÂçÂÂAç»ÂCÃ¥ÂÂæ°æ®çÂÂæ¶åÂÂï¼Â交æ¢æºåªä¼Âç»ÂCÃ¥ÂÂæ°æ®ãÂÂè¿Â个æ¶åÂÂBÃ¥ÂÂDé½æ¶ä¸Âå°æ°æ®ãÂÂä¸Âä½Âæ¶ä¸Âå°ï¼ÂBÃ¥ÂÂDè¿Âå¯以å¨Aä¸ÂCéÂÂä¿¡æÂÂé´è¿Âè¡ÂéÂÂä¿¡ï¼Âè¿Âå°±è¿Âä¸ÂæÂ¥æÂÂé«ÂäºÂç½Âç»ÂçÂÂå©ç¨æÂÂçÂÂãÂÂ
ç½Âç»Âå¨åÂÂå±ÂçÂÂÃ¥ÂÂæ¶ï¼Â计ç®Âæºä¹Âå¨åÂÂå±Âï¼Â两å°计ç®Âæºè¿Âè¡ÂéÂÂä¿¡ï¼Âæ¬质ä¸Âæ¯两å°计ç®Âæºä¸ÂçÂÂè¿Âç¨Âè¿Âè¡ÂéÂÂä¿¡ï¼Âé£ä¹Âä¸Âå°计ç®Âæºæ¯å¯以è¿Âè¡Âå¤Â个è¿Âç¨ÂçÂÂï¼Âé£ä¹Âipå±Âä¸ÂæÂ¥çÂÂæÂ¥æÂÂï¼Â该交ç»Âåª个è¿Âç¨Âå¢ï¼Âç±æ¤就å¼ÂåºäºÂä¼ è¾Âå±Âï¼Âä¼ è¾Âå±Âå¼Âå ¥äºÂ端å£è¿Â个æ¦Â念ï¼Âæ¥解å³è¿Â个é®é¢Âï¼Âipå ä¸Â端å£ï¼Âå°±è½çÂ¥éÂÂæÂ¥æÂÂ交ç»Âåª个è¿Âç¨Âè¿Âè¡Âå¤ÂçÂÂãÂÂä½Âæ°æ®ä¸Âå®Âè½éÂÂå°åÂÂï¼Âè¿Âä¹Âæ¯æÂÂ们ä¸Âé¢æÂÂåºçÂÂæ°æ®丢失é®é¢Âï¼Â丢失äºÂæÂÂä¹ÂÃ¥ÂÂï¼ÂÃ¥ÂÂéÂÂä¼ ï¼Âè¿Âä¹Âå°±æ¯传è¾Âå±Âè¦ÂèÂÂèÂÂçÂÂé®é¢ÂãÂÂä¼ è¾Âå±ÂÃ¥ÂÂ议交ç»Âè¿Âç¨ÂçÂÂæ¯åÂÂèÂÂæµÂï¼ÂéÂÂä¿¡çÂÂÃ¥ÂÂæ¹éÂÂè¦Âå¶å®Âè§ÂÃ¥ÂÂæÂÂè½解æÂÂåºæÂÂæÂÂä¹ÂçÂÂæÂ¥æÂÂï¼Âç±æ¤就å¼ÂåºäºÂåºÂç¨å±ÂÃ¥ÂÂè®®ãÂÂ
é£ä¹Âä½Â为å¼ÂÃ¥ÂÂ人åÂÂï¼ÂæÂÂ们该å¦Âä½Â使ç¨ç½Âç»ÂÃ¥ÂÂè®®ï¼ÂæÂÂä½Âç³»ç»ÂæÂÂä¾ÂäºÂ对åºÂçÂÂå®Âç°ï¼ÂÃ¥ÂÂ个é«Â级è¯Âè¨Âä¸Â莽å 置äºÂè°Âç¨ï¼Âç®åÂÂæ¥说åªæÂÂå ç§Âå¯ä¾ÂåºÂç¨ç¨ÂåºÂ使ç¨çÂÂTCP/IPçÂÂåºÂç¨ç¨ÂåºÂæÂ¥å£ï¼ÂæÂÂèÂÂÃ¥ÂÂçÂÂå°±æ¯ç¾Âå½å å©ç¦Âå©äºÂ大å¦伯å Âå©åÂÂ校为Berkeley UNIXæÂÂä½Âç³»ç»Âå®Âä¹ÂçÂÂAPIï¼Â被称为å¥ÂæÂ¥åÂÂæÂ¥å£(socket interface)ãÂÂ微软å¨堶æÂÂä½Âç³»ç»Âä¸ÂéÂÂç¨äºÂå¥ÂæÂ¥å APIï¼Âä½Âæ¯æÂÂä¸Âç¹ä¸ÂÃ¥ÂÂï¼ÂæÂÂ们称ä¹Â为Windows SocketãÂÂAT&TçÂÂUnix System VçÂÂæ¬å®Âä¹ÂçÂÂæÂ¥å£ï¼Âç®ÂÃ¥ÂÂ为TLI(Transport Layer port)
æÂÂ们å¯以认为å¥ÂæÂ¥åÂÂä½Â为è¿Âç¨ÂÃ¥ÂÂè¿Âè¾Âå±ÂÃ¥ÂÂè®®ä¹Âé´çÂÂæÂ¥å£ï¼ÂÃ¥ÂÂä¸Âé¢è¿Âæ ·ãÂÂ
请注æÂÂ: å¨å¥ÂæÂ¥åÂÂ以ä¸ÂçÂÂè¿Âç¨Âæ¯åÂÂåºÂç¨ç¨ÂåºÂæ§å¶çÂÂï¼ÂèÂÂå¨å¥ÂæÂ¥åÂÂ以ä¸ÂÃ¥ÂÂå±ÂäºÂæÂÂä½Âç³»ç»ÂçÂÂæ§å¶ãÂÂå æ¤ï¼Âåªè¦Âç¨ÂåºÂè¦Â使ç¨TCP/IPÃ¥ÂÂè®®è¿Âè¡ÂéÂÂä¿¡ï¼Âå®Â就忠须è°Âç¨æÂÂä½Âç³»ç»ÂæÂÂä¾ÂçÂÂç½Âç»ÂéÂÂä¿¡æÂ¥å£ãÂÂè¿ÂéÂÂçÂÂå¥ÂæÂ¥åÂÂæ¯ä¸Â个ç¸对æ¥说æÂÂäºÂæ½象çÂÂæ¦Â念ï¼Âé£ä¹Â该æÂÂä¹ÂçÂÂ解è¿ÂéÂÂçÂÂå¥ÂæÂ¥åÂÂå¢? 为ä»Âä¹Â说è¿ÂéÂÂçÂÂå¥ÂæÂ¥åÂÂ? å 为å¨堶ä»Âè¯Âå¢Âä¸Âå¥ÂæÂ¥åÂÂæÂ¥æÂÂå ¶ä»Âè¯Âä¹Âï¼Âä½Âæ¯ä¹Âå«å¥ÂæÂ¥åÂÂãÂÂæÂÂ认为è¿ÂéÂÂçÂÂå¥ÂæÂ¥åÂÂçÂÂå°±æ¯ä¸Â个è§ÂÃ¥ÂÂãÂÂÃ¥ÂÂ约ãÂÂæºå¶ : å½Âç¨ÂåºÂéÂÂè¦Â使ç¨ç½Âç»ÂéÂÂä¿¡æ¶ï¼Âå¿ é¡»é¦Âå Âè°Âç¨æÂÂä½Âç³»ç»ÂæÂÂä¾ÂçÂÂSocketæÂ¥å£ï¼Âä¹Âå¯以称ä¹Â为åÂÂåºSocketç³»ç»Âè°Âç¨ï¼Â请æ±ÂæÂÂä½Âç³»ç»ÂÃ¥ÂÂ建ä¸Â个”å¥ÂæÂ¥åÂӋÂÂè¿Â个è°Âç¨çÂÂå®Âé æÂÂæÂÂå°±æ¯请æ±ÂæÂÂä½Âç³»ç»ÂæÂÂç½Âç»ÂéÂÂä¿¡æÂÂéÂÂè¦ÂçÂÂçÂÂä¸ÂäºÂèµÂæºÂ(CPUæ¶é´,ç½Âç»Â带宽ãÂÂÃ¥ÂÂå¨å¨空é´çÂÂ)Ã¥ÂÂé Âç»Â该åºÂç¨è¿Âç¨ÂãÂÂæÂÂä½Âç³»ç»Â为è¿ÂäºÂèµÂæºÂçÂÂæÂȌÂÂÃ¥ÂÂ建ä¸Â个å¥ÂæÂ¥åÂÂæÂÂ述符çÂÂå·ç Â(å°ÂçÂÂæ´æ°)æ¥表示ï¼Âç¶åÂÂå°Âè¿Â个å¥ÂæÂ¥åÂÂæÂÂ述符è¿ÂÃ¥ÂÂç»ÂåºÂç¨è¿Âç¨ÂãÂÂæ¤åÂÂï¼ÂåºÂç¨è¿Âç¨ÂæÂÂè¿Âè¡ÂçÂÂç½Âç»ÂæÂÂä½Â(建ç«Âè¿ÂæÂ¥ãÂÂæ¶åÂÂæ°æ®ãÂÂè°Âæ´ç½Âç»ÂéÂÂä¿¡åÂÂæ°çÂÂ)é½忠须使ç¨è¿Â个å¥ÂæÂ¥åÂÂæÂÂ述符ãÂÂ
å°ç°å¨为æ¢ä¸ÂÃ¥ÂÂé½å¾Â好ï¼Âä¸Â好çÂÂæ¯ï¼ÂæÂÂ们çÂÂä¿¡æ¯æ¯æÂÂæÂÂï¼ÂæÂÂ被çªÂÃ¥ÂÂ篡æ¹çÂÂé£Âé©ï¼Âè¦Âé²æ¢çªÂÃ¥ÂÂÃ¥ÂÂ篡æ¹ï¼ÂæÂÂ们å¯以使ç¨SSL/TLSÃ¥ÂÂè®®, 详ç»ÂçÂÂå¯以åÂÂçÂÂ:
- æÂÂ们æÂ¥èÂÂèÂÂHTTPSå§
è¿Â个系åÂÂèÂÂèÂÂçÂÂ使ç¨JavaçÂÂAPIÃ¥ÂÂåºä¸Â个BIOÃ¥ÂÂNIO模å¼Âä¸Âé¢çÂÂHTTP/HTTPSæÂÂå¡å¨ï¼ÂæÂÂäºÂä¸Âé¢çÂÂçÂ¥è¯Âï¼ÂæÂÂ们已ç»Â对ç½Âç»ÂæÂÂä¸Â个åºæÂÂäºÂ解äºÂï¼Âä¸Âé¢就å¼Âå§Âç¨JavaæÂÂ建HTTP/HTTPSæÂÂå¡å¨ãÂÂ
BIO模å¼ÂçÂÂæÂÂå¡å¨
BIO/Ã¥ÂÂNIOå¤ÂçÂÂè¿ÂæÂ¥çÂÂçÂÂçÂ¥ä¸ÂÃ¥ÂÂï¼Âä½Âæ¯報åÂÂç¹é½æ¯使ç¨äºÂTCPÃ¥ÂÂè®®ï¼Âä¹Âå°±æ¯å®Â们é½éÂÂè¦ÂçÂÂå¬端å£ï¼Âåªæ¯å¯å¨çÂÂæ¶åÂÂå¤ÂçÂÂå¤ÂçÂÂ请æ±ÂçÂÂæ¹å¼Âä¸ÂÃ¥ÂÂï¼ÂæÂÂ们æ½象åºæÂ¥ä¸Â个åº类ï¼ÂæÂÂ们就å§Âä¸Âå½åÂÂ为Server, è¿Â个Serveræ¯ä¸Â个æ½象类 ï¼ÂæÂÂ们éÂÂè¿ÂServerSocketChannelè¿Â个类çÂÂå¬端å£ï¼ÂæÂÂ以Serverç±»éÂÂé¢éÂÂè¦ÂæÂÂä¸Â个ServerSocketChannelæÂÂÃ¥ÂÂÃ¥ÂÂéÂÂï¼Âå¨ServerSocketChannelæÂÂ们å¯以é Âç½®å½ÂÃ¥ÂÂçÂÂ使ç¨åªç§Âç½Âç»Â模åÂÂ, NIOè¿Âæ¯BIOï¼Â
// true 代表BIO,false代表NIO
public final SelectableChannel configureBlocking(boolean block)
é»Â认模å¼Âå³æ¯BIO,æÂÂ们å½ÂÃ¥ÂÂæÂÂ建çÂÂå°±æ¯BIO模å¼Âä¸Âé¢çÂÂHTTPæÂÂå¡å¨ï¼ÂæÂÂ们ä¸Âé¢说å°æÂÂ们æ³è¦Â使ç¨åºÂç¨å±ÂçÂÂÃ¥ÂÂè®®éÂÂè¦Â端å£ï¼ÂæÂÂ以Serverè¿Â个æ½象类éÂÂé¢è¿ÂéÂÂè¦Âä¸Â个端å£åÂÂå§ÂÃ¥ÂÂéÂÂï¼ÂæÂÂ们è¿Âæ³è¦ÂæÂÂ们çÂÂHTTPæÂÂå¡å¨æ¯æÂÂHTTPSÃ¥ÂÂè®®ï¼Âä½ÂæÂÂå¸ÂæÂÂè¿Â个æ¯çµ活é Âç½®çÂÂï¼Âé£ä¹ÂServerä¹ÂéÂÂè¦Âä¸Â个æÂÂÃ¥ÂÂÃ¥ÂÂéÂÂæÂ¥åÂÂæ¢HTTPãÂÂHTTPS模å¼Âï¼Âé¤æ¤ä¹Âå¤Âï¼ÂTCPæ¯é¢åÂÂè¿ÂæÂ¥çÂÂï¼Âä½Âæ¯æÂÂå¡端å¤ÂçÂÂ客æ·端请æ±Â建ç«ÂçÂÂè¿ÂæÂ¥ä¹ÂéÂÂè¦Âæ¶é´ï¼ÂServerSocketä¼Âç»´æ¤ä¸Â个éÂÂÃ¥ÂÂï¼Âè¿Â没æÂ¥å¾ÂÃ¥ÂÂå¤ÂçÂÂçÂÂè¿Âæ¥就ä¼Âæ¾å°è¿Â个éÂÂÃ¥ÂÂéÂÂé¢ï¼Âå¦ÂæÂÂéÂÂÃ¥ÂÂå·²ç»Â满äºÂï¼Âå°±ä¼ÂæÂÂåºè¿Âæ¥被æÂÂç»ÂçÂÂå¼Â常ã æÂÂ以æÂÂ们çÂÂæÂÂÃ¥ÂÂÃ¥ÂÂéÂÂè¦Âè¦ÂæÂÂæ§å¶éÂÂÃ¥ÂÂ大å°ÂçÂÂÃ¥ÂÂæ°ãÂÂ
å°ç°å¨为æ¢ï¼ÂæÂÂ们就å¯以éÂÂè¿ÂServerSocketChannelæÂ¥æ¿å°SocketChanneläºÂï¼ÂæÂÂä½Âç³»ç»Âä¼Âå°Âæ°æ®éÂÂè¿ÂéÂÂéÂÂéÂÂå ¥å°Bufferä¸Âï¼Âé£è¿ÂéÂÂæÂÂ们å¯以å¨设计ä¸Â个类ï¼Âå°ÂéÂÂéÂÂçÂÂæ°æ®å¤ÂçÂÂå°ByteBufferä¸Âï¼Âé£æ¢ç¶è¦Âå¤ÂçÂÂå°è¿Â个ByteBufferéÂÂé¢ï¼ÂæÂÂ以æÂÂ们è¿Â个类éÂÂéÂÂè¦ÂæÂÂä¸Â个ByteBufferçÂÂæÂÂÃ¥ÂÂÃ¥ÂÂéÂÂï¼Âè¿ÂéÂÂæÂÂ们ç®ÂÃ¥ÂÂçÂÂ讲ä¸Âä¸ÂByteBufferï¼Âæ¾ÂÂçÂÂæÂÂè·¯æ¯å¨ç¨å°çÂÂåªäºÂæ¦Â念çÂÂæ¶åÂÂï¼Âå°±ä¼Â讲åªäºÂï¼Â讲çÂÂÃ¥ÂÂ好å¤Âç¨ãÂÂè¦Âç»ÂSocketChannel读ï¼Âé¦Âå ÂæÂÂ们å¾ÂÃ¥ÂÂé ByteBufferè¿Â个对象:
ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
æÂÂ们å¯以å°ÂByteBufferå½ÂÃ¥ÂÂä¸Â个裠æ°æ®çÂÂ容å¨ï¼Âé£对äºÂ容å¨æÂÂ们èªç¶就堳å¿Âå¦Âä½ÂÃ¥ÂÂÃ¥ÂÂï¼Âé£å¦Âä½ÂÃ¥ÂÂå¢ï¼ÂByteBufferéÂÂé¢以putå¼Â头çÂÂå°±æ¯å°Âæ°æ®æ¾堥ByteBufferä¸ÂçÂÂæ¹æ³Âï¼Âå¦ÂæÂÂæÂÂ们æ¾堥ByteBufferçÂÂæ°æ®趠è¿ÂäºÂ设å®ÂçÂÂ大å°Âï¼Âå°±ä¼ÂæÂÂåºBufferOverFlowExceptionè¿Â个å¼Â常:
ByteBuffer byteBuffer = ByteBuffer.allocate(1);
byteBuffer.put("hello world".getBytes(StandardCharsets.UTF_8));
Ã¥ÂÂçÂÂé®é¢Âï¼ÂæÂÂ们解å³äºÂï¼Âä¸Âé¢æÂÂ们æ¥解å³å¦Âä½ÂÃ¥ÂÂçÂÂé®é¢Âï¼Âå¨读ä¹ÂÃ¥ÂÂï¼ÂæÂÂ们éÂÂè¦Âä»Âç»Âä¸Âä¸ÂBufferçÂÂå 个éÂÂè¦Âå±Âæ§ï¼Âæ¥帮å©æÂÂ们çÂÂ解æÂÂ们åÂÂæ°æ®ï¼Â为ä»Âä¹Âè¦Âè¿Âä¹ÂÃ¥ÂÂãÂÂå¨ByteBufferéÂÂæÂÂ以ä¸Âå 个åÂÂéÂÂ:
-
position: ä¸Âä¸Â个å°Âè¦ÂÃ¥ÂÂå ¥æÂÂ读åÂÂçÂÂæ°ç»Âä¸Âæ Â
-
capacity: ByteBufferçÂÂ大å°Â
-
limit: 第ä¸Â个ä¸Âè½读ä¸Âè½åÂÂçÂÂæ°ç»Âä¸Âæ Â
ByteBufferå¨æªæ¾堥æ°æ®ä¹ÂÃ¥ÂÂ, positionæ¯0ï¼Âcapacityæ¯4096ï¼ÂlimitÃ¥ÂÂæ¯4096ãÂÂä¸Âé¢æÂÂ们æ¾äºÂæ°æ®è¿Âå ¥ByteBufferï¼ÂæÂÂå°±åªæ³读æÂÂæ°æ®çÂÂä½Âç½®ï¼Âé£ä¹ÂåªéÂÂè¦Âå°ÂpositionèµÂå¼ç»Âlimitå°±è¡Âï¼Âç¶åÂÂå°Âpositionæ¾å°0ï¼Âè¿Âä¹Âå°±æ¯ByteBufferä¸Âflipæ¹æ³ÂÃ¥ÂÂçÂÂäºÂãÂÂç°å¨æÂÂ们已çÂ¥çÂÂæ¯, éÂÂè¿ÂServerSocketChannelçÂÂacceptæ¹æ³Âå¨é»å¡ÂI/O模å¼Âä¸Âï¼Âç´å°è¿Âæ¥建ç«Âï¼ÂæÂÂä¼Âè¿ÂÃ¥ÂÂç»ÂæÂÂ们ä¸Â个SocketChannelï¼ÂæÂÂ们å¯以éÂÂè¿ÂSocketChannelå°Âæ°æ®读åÂÂå°ByteBufferä¸Âï¼Âé£ä¹Â对äºÂTCPÃ¥ÂÂè®®æ¥说ï¼ÂTCPæ°æ®çÂÂè´Âè½½1400Ã¥ÂÂèÂÂï¼ÂæÂÂ以åºÂç¨å±Âå¦ÂæÂÂ交ä»Âç»Âä¼ è¾Âå±ÂçÂÂæ°æ®为1500Ã¥ÂÂèÂÂï¼Âé£ä¹Âå°±éÂÂè¦Â两个TCPæ°æ®å 传è¾Âï¼ÂæÂÂ们å¯以çÂÂ解为æÂÂæÂÂ两个å 裹åÂÂéÂÂï¼Âé£对äºÂSocketChannelæ¥说ï¼ÂæÂÂ们èªç¶就堳å¿Âä»ÂçÂÂ读åÂÂæ¹å¼Âï¼Âæ¯å°äºÂå¤Âå°Âæ°æ®å 就读å¤Âå°Âï¼Âè¿Âæ¯根æ®ByteBufferçÂÂå©ä½Â容éÂÂå»读åÂÂå¢@å¦ÂæÂÂæ¯å°äºÂå¤Âå°Âæ°æ®å 就读å¤Âå°Âï¼Âé£ä¹ÂæÂÂ们çÂ¥éÂÂByteBufferæ¥说ï¼Â趠è¿ÂäºÂé¢Â设å¼çÂÂ容éÂÂï¼Âå°±ä¼ÂæÂÂå¼Â常@æÂÂ们åºÂå½Âæ ¹æ®TCPæÂÂ大æ°æ®å è¿Âè¡Âæ©容ï¼Âå¦ÂæÂÂByteBufferçÂÂå©ä½Â容éÂÂå°ÂäºÂæÂÂ大TCPæ°æ®å ï¼Âé£ä¹Âå°±å½Âè¿Âè¡Âæ©容ï¼Âè¿Âç§ÂÃ¥ÂÂ设建ç«Âå¨SocketChannel读çÂÂæ¯ä¸Â个æÂÂä¸Â个TCPæ°æ®å ï¼Âå 为SocketChannelçÂÂreadæ¹æ³Âå¨Oracle JDKä¸Âæ¯ä¸Âå¼ÂæºÂçÂÂï¼ÂæºÂç Â注éÂÂä¸ÂÃ¥ÂÂ没åÂÂ读åÂÂçÂÂè¡Â为ï¼Âé£æÂÂ们å¦Âä½ÂéÂÂ对ByteBufferè¿Âè¡Âæ©容å¢, æ¯Âç«ÂSocketChannelÃ¥ÂÂByteBufferéÂÂé¢读åÂÂæ°æ®çÂÂè¡Â为ä¹Âä¸Âå½ÂæÂÂ们æ§å¶ï¼Âå ¶å®ÂæÂÂæ¯为è¿Â个é®é¢ÂæÂÂèÂÂè¿Âä¸ÂéµçÂÂï¼ÂæÂÂå°Âè¿Â个é®é¢Âå®Âä¹Â为ï¼Âå¨åºÂç¨å±ÂæªéÂÂå¶æÂ¥æÂÂ大å°ÂçÂÂÃ¥ÂÂæÂÂï¼Â交ä»Âç»Âä¼ è¾Âå±ÂæÂ¥æÂÂçÂÂ大å°Âä¸Âåºå®ÂçÂÂæ åµä¸Âï¼Â该å¦Âä½ÂéÂÂæ©æÂÂä¼Âæ©容æ¶æºã æÂÂå°Âè¿Â个é®é¢Âæ½象为äºÂä¸Â个æ°å¦é®é¢Âï¼Âè¦è¦æÂÂç´¢ï¼Âä¸ÂæÂÂÃ¥ÂÂ交è°Âä¹ÂÃ¥ÂÂï¼ÂæÂÂÃ¥ÂÂ建议æÂÂÃ¥ÂȍÂÂNettyæ¯å¦Âä½Â对ByteBufè¿Âè¡Âæ©容çÂÂ, ByteBufæ¯Netty对ByteBufferçÂÂæ©å±Âç±»ï¼ÂæÂÂè½ç¶çÂÂçÂÂæÂÂByteBufæ¯å¦Âä½Âæ©容çÂÂï¼Âä½Âæ¯æÂÂè¿Âæ¯æ æ³ÂÃ¥ÂÂçÂÂæÂÂèª己æÂÂåºçÂÂé®é¢Âï¼ÂæÂÂä¸Â天æÂÂå¨堬å¸è¿Â个é®é¢Âè¿Âå¨æÂÂçÂÂèÂÂæµ·ä¸ÂçÂÂæÂÂï¼ÂæÂÂ裠äºÂOpen JDKï¼ÂOpenJDKæ¯å¼ÂæºÂçÂÂï¼ÂæÂÂ们å¯以çÂÂOpen JDKçÂÂå®Âç°ï¼ÂSocketChannelæ¯ä¸Â个æ½象类ï¼Âreadæ¹æ³Âæ¯ä¸Â个æ½象æ¹æ³Âï¼ÂæÂÂ以æÂÂ们è¿Âå¾ÂçÂÂSocketChannelçÂÂå®Âç°类ï¼ÂSocketChannelImpl, IDEAå¯以帮æÂÂ们èªå¨寻æ¾åÂÂç±»ï¼ÂæÂÂçµèÂÂä¸ÂçÂÂOpen JDKæ¯JDK11ï¼Âreadæ¹æ³ÂçÂÂå®Âç°å¦Âä¸Â:
public int read(ByteBuffer buf) throws IOException {
Objects.requireNonNull(buf);
readLock.lock();
try {
ensureOpenAndConnected();
boolean blocking = isBlocking();
int n = 0;
try {
beginRead(blocking);
// check if input is shutdown
if (isInputClosed)
return IOStatus.EOF;
if (blocking) {
do {
n = IOUtil.read(fd, buf, -1, nd);
} while (n == IOStatus.INTERRUPTED && isOpen());
} else {
n = IOUtil.read(fd, buf, -1, nd);
}
} finally {
endRead(blocking, n > 0);
if (n <= 0 && isInputClosed)
return IOStatus.EOF;
}
return IOStatus.normalize(n);
} finally {
readLock.unlock();
}
}
è¿ÂéÂÂæÂÂ们åª堳注æÂÂ纵ByteBufferçÂÂ代ç Âï¼Âå ¶ä»ÂæÂÂ们ä¸ÂÃ¥ÂÂç Â究ï¼ÂæÂÂç»Âè¿Âæ¯IOUtilæÂ¥å°Âæ°æ®æ¾堥ByteBufferä¸Âï¼ÂæÂÂ们æÂ¥çÂÂæÂ¥çÂÂIOUtilçÂÂreadæ¹æ³Âï¼Â对åºÂçÂÂå®Âç°å¦Âä¸Â:
static int read(FileDescriptor fd, ByteBuffer dst, long position,
boolean directIO, int alignment, NativeDispatcher nd)
throws IOException
{
if (dst.isReadOnly())
throw new IllegalArgumentException("Read-only buffer");
if (dst instanceof DirectBuffer)
return readIntoNativeBuffer(fd, dst, position, directIO, alignment, nd);
// Substitute a native buffer
ByteBuffer bb;
int rem = dst.remaining();
if (directIO) {
Util.checkRemainingBufferSizeAligned(rem, alignment);
bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
} else {
bb = Util.getTemporaryDirectBuffer(rem);
}
try {
int n = readIntoNativeBuffer(fd, bb, position, directIO, alignment,nd);
bb.flip();
if (n > 0)
dst.put(bb);
return n;
} finally {
Util.offerFirstTemporaryDirectBuffer(bb);
}
}
æÂÂ们å¯以çÂÂå°å¨readæ¹æ³ÂéÂÂé¢åÂÂÃ¥ÂÂ建äºÂä¸Â个ByteBufferï¼Âç¶åÂÂè°Âç¨äºÂByteBufferçÂÂremainingæ¹æ³Âï¼Âè¿Â个æ¹æ³ÂçÂÂä½Âç¨æ¯è·åÂÂå½ÂÃ¥ÂÂByteBufferè¿Âå©å¤Âå°Â容éÂÂï¼ÂdirectIOæ¯falseï¼Âå°达çÂÂTCPæ°æ®å æ¯å Âè¿ÂäºÂreadæ¹æ³Âèª己åÂÂ建çÂÂBytebufferä¸Âï¼Âç¶åÂÂå¨æ¾堥æÂÂ们传堥çÂÂBytebufferä¸ÂãÂÂå°ç°å¨为æ¢æÂÂ们就ç»Âæ¡ÂäºÂï¼ÂæÂÂ们å¨ç¨SocketChannel读ä¹ÂÃ¥ÂÂä¹ÂåªéÂÂçÂÂä¸Âå©ä½Â容éÂÂï¼ÂæÂÂ们å¯以æÂÂÃ¥ÂÂ设å®Âä¸Â个éÂÂå¼为ByteBufferçÂÂç¾åÂÂä¹ÂäºÂï¼Âå¦ÂæÂÂå©ä½ÂçÂÂå°ÂäºÂç¾åÂÂä¹ÂäºÂï¼ÂæÂÂ们就å¯以认为ByteBufferå¿«ç¨å®ÂäºÂï¼Âç¶åÂÂæÂÂ们就对ByteBufferè¿Âè¡Âæ©容ï¼Âè¿Â个æ©容çÂÂæ¶æºï¼Âä½ å¯以设å®Â为ByteBufferå©ä½Â容éÂÂ为0ï¼Âç¨å®ÂäºÂÃ¥ÂÂè¿Âè¡Âæ©容ï¼Âä½ÂæÂÂ们åºÂå½Âé¿å Âé¢Âç¹Âæ©容ï¼ÂæÂÂ以æÂÂè¿ÂéÂÂä¸Â建议å¨ByteBufferç¨å®ÂäºÂÃ¥ÂÂè¿Âè¡Âæ©容ï¼ÂæÂÂ设置çÂÂæ¯ç¾åÂÂä¹ÂäºÂï¼Âä½ ä¹Âå¯以设置为ç¾åÂÂä¹ÂÃ¥ÂÂï¼ÂæÂÂ为ä»Âä¹Â设置为ç¾åÂÂä¹ÂäºÂå¢ï¼Âè¿Âæ¯æÂÂÃ¥ÂÂèÂÂå«人çÂÂ设计ï¼Âè³äºÂ为ä»Âä¹Âå«人è¦Â设å®Â为å©ä½Â容éÂÂå°ÂäºÂç¾åÂÂä¹ÂäºÂï¼ÂæÂÂæÂÂæ¶è¿Â没èÂÂç³»å°é£ä½Âä½Âè ï¼Â为ä»Âä¹Âè¿Âä¹Â设计ã 堶å®ÂæÂÂ们ä¹Âå¯以ä¸Âæ©容ï¼Âç®ÂÃ¥ÂÂä¸Âç¹就æ¯设å®ÂæÂ¥æ¶çÂÂæÂÂ大æÂ¥æÂÂé¿度ï¼Âç¶åÂÂByteBufferå°±åÂÂé Âè¿Â个大å°Âï¼Âè¿Âä¹ÂÃ¥ÂÂä¼¼ä¹ÂæÂÂäºÂ浪费ï¼ÂæÂÂ们æ¬ç¯ÂéÂÂç¨çÂÂ设计就æ¯å©ä½Â容éÂÂå°ÂäºÂç¾åÂÂä¹ÂäºÂ对ByteBufferè¿Âè¡Âæ©容ãÂÂ
æ©容çÂÂé®é¢Â解å³äºÂï¼ æÂÂ们çÂÂByteBufferå¯以æ¾çÂÂä¸Â客æ·端åÂÂéÂÂçÂÂæÂ¥æÂÂäºÂï¼Âé£ä¹Âè¿ÂæÂÂä¸Â个é®é¢Âå°±æ¯ä»Âä¹Âæ¶åÂÂï¼Â读åÂÂæ°æ®å®Âæ¯Âï¼Âç¶åÂÂ对æ°æ®è¿Âè¡Â解æÂÂãÂÂ对äºÂHTTP请æ±ÂæÂ¥æÂÂæ¥说æ¯æÂÂç»ÂæÂÂ符å·çÂÂï¼ÂæÂÂ以æÂÂ们å¯以å¤æÂÂByteBufferä¸ÂçÂÂæ°æ®æ¯å¦æÂÂç»ÂæÂÂ符ï¼Âå¦ÂæÂÂæÂÂ就代表HTTP请æ±ÂçÂÂæ°æ®解æÂÂå®Âæ¯Âï¼Âå¯以交ç»ÂæÂ¥æ¶æ¹æÂ¥å¤ÂçÂÂäºÂãÂÂ注æÂÂæÂÂ们æ¬次æÂÂ建çÂÂHTTPæÂÂå¡å¨ç¸对åÂÂ级ä¸Âç¹ï¼Âåªæ¯æÂÂHTTP 1.0ï¼ÂèÂÂä¸Âç¨çÂÂI/O模åÂÂæ¯BIOï¼ÂæÂÂ以æÂÂ们ä¹Âå¯以å¤æÂÂå¦ÂæÂÂSocketChannel没æÂÂå¯以读çÂÂæ°æ®äºÂï¼Â代表HTTP请æ±ÂçÂÂæ°æ®解æÂÂå®Âæ¯ÂäºÂãÂÂæÂÂ们å¯以å°Âæ°æ®交ç»Âä¸Âé¨解æÂÂæ°æ®çÂÂç»Â件æÂ¥è¿Âè¡Âå¤ÂçÂÂï¼Âè¿Â个ç»Â件你å¯以çÂÂ解为类ãÂÂ
å°ç°å¨为æ¢æÂÂ们çÂÂæµÂç¨ÂæÂÂæÂ¥æ¶æ°æ®ï¼Â解æÂÂæ°æ®ï¼Âæ ¹æ®请æ±ÂæÂÂ建åÂÂåºÂï¼Âç¶åÂÂÃ¥ÂÂéÂÂÃ¥ÂÂåºÂãÂÂæÂÂ们讲äºÂè¿Âä¹Âå¤ÂçÂÂ论ï¼Âå·²ç»Âå¯以å¼Âå§ÂçÂÂæÂÂÃ¥ÂÂæÂ¥æ¶æ°æ®åÂÂ解æÂÂæ°æ®çÂÂé¨åÂÂäºÂï¼ÂæÂÂ们æ¬系åÂÂçÂÂé¢ÂæÂÂæ¯ç¨JavaçÂÂæ ÂÃ¥ÂÂåºÂæÂ¥å®Âç°BIO/NIO模å¼Âä¸ÂçÂÂHTTP/HTTPSæÂÂå¡å¨ï¼Âç¶åÂÂç¨NettyæÂ¥å®Âç°HTTPæÂÂå¡å¨ï¼Â设计çÂÂHTTPæÂÂå¡å¨æ¯Âè¾Âç®ÂÃ¥ÂÂï¼ÂåªåÂÂåºÂçÂÂç®ÂÃ¥ÂÂ请æ±ÂãÂÂÃ¥ÂÂé¢éÂÂæÂ¥çÂÂæ©å±ÂãÂÂ
å 为æÂÂ们å¯以åÂÂå©ServerSocketChannelæÂ¥é Âç½®BIOè¿Âæ¯NIOï¼ÂèÂÂBIOÃ¥ÂÂNIOå°±æ¯å¨堷ä½ÂçÂÂè¡Â为ä¸ÂæÂÂæÂÂä¸ÂÃ¥ÂÂï¼Âå¨åÂÂå§ÂÃ¥ÂÂå±Âæ§æ¹é¢æ¯堷å¤Âå ±æ§çÂÂï¼ÂæÂÂ以è¿ÂéÂÂæÂÂ们é¦Âå Â建ç«ÂäºÂä¸Â个æ½象类Serverï¼ÂServerè´Âè´£åÂÂå§ÂÃ¥ÂÂ端å£ï¼Âbacklogï¼Âå¯å¨çÂÂæ¯HTTP模å¼Âè¿Âæ¯HTTPS模å¼Âï¼Âæ¬ç¯Âä¸Âä»Âç»ÂHTTPSçÂÂå®Âç°ï¼ÂæÂÂ们å°ÂHTTPSçÂÂå®Âç°æ¾å¨åÂÂé¢ä»Âç»ÂãÂÂ
æ¬ç¯ÂæÂÂ们åÂÂçÂÂæ¯ä¸Â个HTTPæÂÂå¡å¨, è¿ÂéÂÂæÂÂæ³åÂÂçÂÂçµ活ä¸ÂäºÂï¼Âå¨å¯å¨çÂÂæ¶åÂÂå¯以æÂÂå®Â端å£ãÂÂbacklogçÂÂçÂÂãÂÂæÂÂ们ç°å¨çÂ¥éÂÂJava å¯å¨çÂÂå½令å¦Âä¸ÂæÂÂ示:
java -jar jarÃ¥ÂÂ
å¨jarÃ¥ÂÂÃ¥ÂÂé¢è·ÂçÂÂÃ¥ÂÂæ°ä¼Â被mainå½æ°çÂÂargsæÂ¥æ¶ï¼ÂæÂÂ们æÂ¥æµÂè¯Âä¸Âä¸Â, é¦Âå ÂæÂÂ们æÂÂä¸Â个Spring Boot Webå·¥ç¨Âï¼Âç¶åÂÂæÂÂ们å¨mainå½æ°éÂÂé¢æÂÂå°ä¸Âä¸ÂargsÃ¥ÂÂæ°:
@SpringBootApplication
public class SsmApplication {
public static void main(String[] args) {
System.out.println(Arrays.toString(args));
SpringApplication.run(SsmApplication.class, args);
}
}
ç¶åÂÂæÂÂ们å¨IDEAçÂÂterminaléÂÂé¢è¾Âå ¥:
mvn package
ç¶åÂÂå¨targetéÂÂé¢就å¯以çÂÂå°æÂÂå 好çÂÂjaräºÂï¼Âç¶åÂÂæÂÂ们以å½令è¡ÂçÂÂæ¹å¼Âå¯å¨è¿Â个jar:
java -jar jarå hello
å°±è½å¨å¯å¨çÂÂæ¶åÂÂçÂÂè§Âï¼Âé¦Âå Âå¨ç»Â端éÂÂé¢è¾ÂåºçÂÂæ¯hello:
æÂÂ们ä¸Â荨IDEAå¼ÂÃ¥ÂÂï¼Âå¨IDEAéÂÂé¢æ³é Âç½®è¿Â个åÂÂæ°å¯以éÂÂè¿Âå¦Âä¸Âæ¥骤:
æÂÂ们åÂÂé¢æÂÂå°æÂÂ们ä¼Âç¨åÂÂçÂÂNIOãÂÂBIOï¼ÂNettyå®Âç°HTTPæÂÂå¡å¨ï¼ÂæÂÂ们就读åÂÂprogram arumentsæÂ¥å³å®Âå½ÂÃ¥ÂÂçÂÂHTTPæÂÂå¡å¨æ¯åªç§Â模åÂÂï¼ÂæÂÂ以æÂÂ们çÂÂåºç¡ÂServerç±»å¦Âä¸ÂæÂÂ示:
package org.example.http;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.util.Arrays;
/**
* @author xingke
* @date 2023-07-15 15:36
*/
public abstract class Server {
protected ServerSocketChannel serverSocketChannel;
protected SSLContext sslContext;
static int port = 8000;
static int backlog = 1024;
static boolean secure = false;
public Server(int port, int backlog, boolean secure) throws IOException {
// Ã¥ÂÂ建ä¸Â个ServerSocketChannel
serverSocketChannel = ServerSocketChannel.open();
/**
* å¯以éÂÂç¨ip+端å£è¿Â个é¾æÂÂ¥,TCP以é¾æ¥为åÂÂä½Â,å½ÂTCPé¾æÂ¥è¦ÂÃ¥Â
³éÂÂçÂÂæ¶åÂÂï¼Âä¼ÂçÂÂå¾Â
ä¸Â段æ¶é´åÂÂè¿Âè¡ÂÃ¥Â
³éÂÂ,
* å¦ÂæÂÂæÂÂæ³è¦ÂéÂÂç¨端å£,é£ä¹Âchannelå°±æ æ³Âç»Âå®Â,å¨ç»Âå®Âå°对åºÂå°åÂÂä¹ÂÃ¥ÂÂ,设å®ÂéÂÂç¨å°åÂÂãÂÂå³使å¨è¿Â个端å£ä¸ÂçÂÂtcpè¿ÂæÂÂ¥
* å¤ÂäºÂå¤ÂäºÂTIME_WAITç¶æÂÂ,æÂÂ们ä»Âç¶å¯以使ç¨
*/
serverSocketChannel.socket().setReuseAddress(true);
// ç»Âå®Â端å£åÂÂbacklog
serverSocketChannel.bind(new InetSocketAddress(port),backlog);
}
/**
* è¿ÂéÂÂæ¯æ½象æ¹æ³Â,æÂÂ们åÂÂé¢è¦Âç¨NIOÃ¥ÂÂå®Âç°ä¸ÂéÂÂ
* æÂÂ以è¿ÂéÂÂ交ç»ÂÃ¥ÂÂç±»æÂ¥å®Âç°
*/
protected abstract void runServer();
/**
* æÂÂ们è¦ÂÃ¥ÂÂçÂÂæ¯ä¸Â个ç®ÂÃ¥ÂÂçÂÂHTTPæÂÂå¡å¨,
* è¿Â个æÂÂå¡å¨å¯以ä»Âå½令è¡Âæ¹å¼Âå¯å¨çÂÂæ¶åÂÂæÂ¥æ¶åÂÂæ°
* æÂÂ们å¯以éÂÂæ©ä»Âmainå½æ°
* @param args
*/
public static void main(String[] args) throws IOException {
Server server = null;
if (args.length == 0){
System.out.println("http server running default model");
server = new BlockingServer(port,backlog,secure);
server.runServer();
}
// 端å£ç®åÂÂÃ¥Â
Âåºå®Âæ», æÂÂ们ç®åÂÂåª读ä¸Â个åÂÂæ°
if ("B".equals(args[0])){
server = new BlockingServer(port,backlog,secure);
}else if ("N".equals(args[0])){
server = new NonBlockingServer(port,backlog,secure);
}else{
System.out.println("input args error only support B OR N");
return;
}
server.runServer();
}
}
Ã¥ÂÂéÂÂæ°梳çÂÂä¸Âä¸ÂæÂÂ们éÂÂè¦ÂçÂÂç»Â件
å¨JavaéÂÂé¢ä¸ÂÃ¥ÂÂé½æ¯类ï¼Âè¿ÂéÂÂ说çÂÂç»Â件åªæ¯æ¿æ äºÂç¹å«åÂÂè½çÂÂç±»ï¼ÂæÂÂ们就å§Âä¸Âå°Âå ¶å½åÂÂ为ç»Â件ãÂÂæ ¹æ®å¤ÂçÂÂæµÂç¨Âï¼ÂæÂÂè¿ÂéÂÂÃ¥ÂÂÃ¥ÂÂäºÂ以ä¸Âå 个类:
- Server åºç¡Âç±», æ ¹æ®读åÂÂçÂÂÃ¥ÂÂæ°æ¥以ä¸ÂÃ¥ÂÂçÂÂIO模åÂÂå¤ÂçÂÂ请æ±Â
- ServerçÂÂÃ¥ÂÂç±»:
- BlockingServer çÂÂæ£å¤ÂçÂÂ请æ±ÂçÂÂç±» BIO模å¼Â
- NonBlockingServer çÂÂæ£å¤ÂçÂÂ请æ±ÂçÂÂç±» NIO模å¼Â
- ChannelIO è´Âè´£ä»ÂChanneléÂÂé¢读åÂÂæ°æ®å°ByteBufferä¸Â
- RequestServicer 解æÂÂ请池ç»ÂÃ¥ÂÂåºÂ
- Request è¾ å©解æÂÂ请æ±Â
- Reply è¾ å©æÂÂ建åÂÂåºÂ
è¿Âä½ÂæµÂç¨Âå¦Âä¸ÂæÂÂ示:
è¿Âæ¯æÂÂèª己çÂÂÃ¥ÂÂæ³Âï¼Âä½ ä¹Âå¯以æÂÂç §èª己çÂÂæ¹å¼ÂÃ¥ÂȌÂÂ解ï¼ÂæÂÂå°ÂæÂÂåºç¡ÂçÂÂÃ¥ÂÂçÂÂé½åÂÂè¯ÂäºÂ诸åÂÂï¼Â诸åÂÂä¹Âå¯以åÂÂå¨ä¸Â个类éÂÂé¢ï¼Âç¨ä¸ÂÃ¥ÂÂç§ÂÃ¥ÂÂæ ·çÂÂ设计模å¼Âï¼Âé½å¯以æÂÂèª己çÂÂÃ¥ÂÂæ³ÂãÂÂ
BlockingServer
BIO模å¼Âä¸ÂçÂÂ解æÂÂæ°æ®ç¸对ç®ÂÃ¥ÂÂä¸ÂäºÂï¼ÂæÂÂ们åªéÂÂè¦Âè°Âç¨SeverSocketChannelçÂÂacceptæ¹æ³Âï¼Âä¼Âä¸Âç´é»å¡Âï¼Âç´å°è¿ÂæÂ¥å®Â堨建ç«Âï¼Âè¿Âæ¥建ç«Âä¹ÂÃ¥ÂÂæÂÂ们å°ÂSocketChannelä¼ éÂÂç»ÂChannelIOå³å¯ãÂÂæÂÂ以æÂÂ们çÂÂBlockingServerå¯以è¿Âä¹ÂÃ¥ÂÂ:
public class BlockingServer extends Server{
public BlockingServer(int port, int backlog, boolean secure) throws IOException {
super(port, backlog, secure);
}
@Override
protected void runServer() throws IOException {
SocketChannel socketChannel = serverSocketChannel.accept();
ChannelIO channelIO = ChannelIO.getInstance(socketChannel, true);
RequestServicer requestServicer = new RequestServicer(channelIO);
requestServicer.run();
}
}
è·ÂæÂÂ们ä¸Âé¢çÂÂè¿Âä½ÂæµÂç¨Âæ¯ä¸Âæ ·çÂÂï¼Âè¿Âæ¥建ç«Âä¹ÂÃ¥ÂÂæ¿å°SocketChannel, ç¶åÂÂå°ÂSocketChannelä¼ éÂÂç»ÂChannelIOï¼Â读åÂÂéÂÂéÂÂçÂÂæ°æ®ï¼Â读åÂÂå®Âæ°æ®交ç»ÂRequestServicer, 解æÂÂ请æ±Âæ°æ®ï¼Âç»ÂäºÂ客æ·端åÂÂåºÂãÂÂ
ChannelIO
æÂÂ们ä¸Âé¢æÂÂå°æÂÂ们è¦Â解æÂÂ请æ±Âæ°æ®ï¼Âé£就代表è¦Â读åÂÂï¼Âç»ÂäºÂ客æ·端åÂÂåºÂï¼Â代表è¦ÂÃ¥ÂÂï¼ÂChannelIOéÂÂè¦ÂæÂÂä¸Â个读æ¹æ³ÂÃ¥ÂÂÃ¥ÂÂæ¹æ³Âï¼Âå¨读ä¹ÂÃ¥ÂÂæÂÂ们éÂÂè¦ÂByteBufferï¼ÂæÂÂ以æÂÂ们å¨è·å¾ÂChannelIOå®Âä¾ÂçÂÂæ¶åÂÂï¼ÂéÂÂè¦Âé¢Âå ÂÃ¥ÂÂé Âä¸Â个ByteBufferï¼Âå 为HTTPÃ¥ÂÂè®®æªéÂÂå¶æÂ¥æÂÂ大å°Âï¼ÂæÂÂ们çÂÂByteBufferå¯è½就ä¼Â裠ä¸Âä¸Âï¼ÂæÂÂ以æÂÂ们å¨读çÂÂæ¶åÂÂå°±éÂÂè¦Âå¤æÂÂå©ä½Â容éÂÂï¼Âæ ¹æ®å©ä½Â容éÂÂçÂÂå¤Âå°ÂæÂ¥å¤æÂÂæ¯å¦éÂÂè¦Âæ©容ãÂÂ读åÂÂæ°æ®å®Âæ¯Âï¼Âæ°æ®åÂÂå®ÂäºÂï¼ÂæÂÂ们就éÂÂè¦Âå ³éÂÂéÂÂéÂÂï¼ÂæÂÂ以æÂÂ们çÂÂChannelIOå¦Âä¸ÂæÂÂ示:
package org.example.http;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class ChannelIO {
private SocketChannel socketChannel;
private ByteBuffer requestBuffer;
int defaultByteBufferSize = 4096;
private ChannelIO(SocketChannel socketChannel, boolean blocking) throws IOException {
this.socketChannel = socketChannel;
this.requestBuffer = ByteBuffer.allocate(4096);
this.socketChannel.configureBlocking(blocking);
}
public static ChannelIO getInstance(SocketChannel socketChannel, boolean blocking) throws IOException {
return new ChannelIO(socketChannel,blocking);
}
public int read() throws IOException {
// å©ä½ÂçÂÂå°ÂäºÂç¾åÂÂä¹ÂäºÂèªå¨æ©容
resizeByteBuffer(defaultByteBufferSize / 20);
return socketChannel.read(requestBuffer);
}
private void resizeByteBuffer(int remaining) {
if (requestBuffer.remaining() < remaining){
// æ©容ä¸ÂÃ¥ÂÂ
ByteBuffer newRequestBuffer = ByteBuffer.allocate(requestBuffer.capacity() * 2);
// 转为读模å¼Â
requestBuffer.flip();
// å°Âæ§çÂÂbufferæ¾åÂ
¥å°æ°çÂÂbufferä¸Â
newRequestBuffer.put(requestBuffer);
requestBuffer = newRequestBuffer;
}
}
public ByteBuffer getReadBuf(){
return this.requestBuffer;
}
public int write(ByteBuffer byteBuffer) throws IOException{
return socketChannel.write(byteBuffer);
}
public void close() throws IOException{
socketChannel.close();
}
}
ChannelIOæÂÂäºÂï¼Âç°å¨就éÂÂè¦ÂRequestServiceræÂ¥è°Âç¨ChannelIOæÂÂÃ¥ÂÂæ°æ®äºÂãÂÂ
RequestServicer
å¨HTTPÃ¥ÂÂè®®ä¸Âé¢ï¼Âä¸ÂéÂÂå¶æÂ¥æÂÂçÂÂ大å°Âï¼Âé£ä¹ÂTCPÃ¥ÂÂè®®ä¼Â对HTTP交ä»ÂçÂÂæÂ¥æÂÂÃ¥ÂÂå åÂÂéÂÂï¼Âè³äºÂÃ¥ÂÂå 个å æÂÂ们æ æ³Âé¢Â设ï¼ÂæÂÂ以æÂÂÃ¥ÂÂæ°æ®åºÂå½Âæ¯ä¸Â个æ éÂÂ循ç¯ï¼Âè½ç¶HTTPä¸ÂéÂÂå¶æÂ¥æÂÂçÂÂ大å°Âï¼Âä½Âæ¯ä¹Âæ¯æÂÂç»ÂæÂÂ符çÂÂï¼ÂæÂÂ以æÂÂ们å¯以解æÂÂæÂ¥æÂÂå¤æÂÂ解æÂÂå°çÂÂæ°æ®æ¯å¦æÂÂç»ÂæÂÂ符ï¼ÂÃ¥ÂÂæÂÂå¦ä¸Â个æ¡件就æ¯SocketChannel读ä¸Âå°æ°æ®äºÂï¼ÂæÂÂ们ä¹Âå¯以认为读å®ÂäºÂï¼ÂæÂÂ以è¿Â个æ éÂÂ循ç¯ç»ÂæÂÂçÂÂæ¡件æÂÂ两个ï¼Âä¸Âæ¯SocketChannelæ æ°æ®å¯读ï¼ÂäºÂæ¯ä»ÂæÂ¥æ¶å°çÂÂæ°æ®解æÂÂå°äºÂç»ÂæÂÂ符ãÂÂ
ä»ÂæÂ¥æ¶å°çÂÂæ°æ®解æÂÂå°äºÂç»ÂæÂÂ符çÂÂè¿Â个åÂÂè½æÂÂ们æ¾å°Requestè¿Â个类éÂÂé¢ãÂÂ
Request
HTTP 2.0 ä¹ÂÃ¥ÂÂ以\r\nä½Â为ç»ÂæÂÂ符(è¿ÂéÂÂä¸Âç¡®å®Âæ¹äºÂ没)ï¼ÂæÂÂ以æÂÂ们å¤æÂÂç»ÂæÂÂåªéÂÂè¦Âå¤æÂÂByteBufferä¸ÂçÂÂÃ¥ÂÂÃ¥ÂÂ个åÂÂ符æ¯\r\nå³å¯ï¼Âå¤æÂÂæÂ¥æÂÂæ¯å¦æÂ¥æ¶å®Âæ¯ÂçÂÂäºÂæ ç»ÂæÂÂäºÂï¼ÂæÂÂ们æÂ¥ä¸ÂæÂ¥åÂÂçÂÂå¦Âä½Â就解æÂÂæ°æ®è¿Â个é®é¢Âï¼Âä¸ÂåªçÂÂæ¯HTTP请æ±ÂæÂÂ请æ±Âæ¹å¼Â: GET POST HEAD PUTçÂÂï¼ÂæÂÂ们ç®åÂÂ设计çÂÂæ¯åªæ¯æÂÂè¿ÂÃ¥ÂÂç§Âï¼ÂæÂÂ以æÂÂ们ä»Âæ°æ®éÂÂé¢解æÂÂå°请æ±Âæ¹å¼Âï¼Âå¦ÂæÂÂä¸Âæ¯æÂÂ们æ¯æÂÂçÂÂ请æ±Âæ¹å¼Âï¼ÂæÂÂ们就éÂÂè¦ÂÃ¥ÂÂè¯Â客æ·端ï¼Âbad requestï¼Âä¹Âå°±æ¯400ãÂÂè¿ÂéÂÂæÂÂ们解æÂÂå°æ°æ®åÂÂä¹ÂÃ¥ÂÂï¼Âå°±åÂÂå¤Âä¸Â个hello worldç»Â客æ·端ãÂÂ
æÂÂ们å¨æÂÂä¸Âä¸ÂRequestå ·å¤ÂçÂÂÃ¥ÂÂè½ï¼Âé¦Âå Âæ¯å¤æÂÂæÂ¥æÂÂæ¯å¦æÂ¥æ¶å®Âæ¯Âï¼ÂÃ¥ÂÂæÂÂå°±æ¯解æÂÂæÂ¥æÂÂï¼Âå¨解æÂÂæÂ¥æÂÂçÂÂæ¶åÂÂæÂÂ们é¦Âå Âè·åÂÂ请æ±Âæ¹å¼Âï¼Âå¦ÂæÂÂ请æ±Âæ¹å¼Âä¸Â被æ¯æÂÂï¼ÂÃ¥ÂÂåºÂå°±æ¯400ï¼Âå¦ÂæÂÂæ¯æ¯æÂÂçÂÂæ¹å¼Âï¼ÂæÂÂ们就æÂ¥çÂÂå¾Âä¸Â解æÂÂï¼Âç¨解æÂÂçÂÂä¿¡æ¯æÂÂé URIè¿Â个类ï¼ÂæÂÂè¿ÂéÂÂçÂÂ设计æ¯RequestæÂÂä¸Â个æÂÂÃ¥ÂÂÃ¥ÂÂéÂÂä¸Â个æ¯请æ±Âæ¹å¼Âï¼Âè¿Â个æÂÂ们ç¨ä¸Â个å é¨类æÂ¥æ¿æÂ¥ï¼Âä¸Â个æ¯HTTPçÂÂæ¬ï¼Âä¸Â个æ¯hostnameã æÂÂ以æÂÂ们çÂÂRequestç±»æÂÂæÂÂå¦Âä¸Â:
public class Request {
private Action action;
private URI uri;
private String version;
public Request(Action action, URI uri, String version) {
this.action = action;
this.uri = uri;
this.version = version;
}
static class Action{
private String name;
static Action GET = new Action("GET");
static Action POST = new Action("POST");
static Action PUT = new Action("PUT");
static Action HEAD = new Action("HEAD");
public Action(String name) {
this.name = name;
}
public String toString(){
return this.name;
}
static Action parse(String s){
if ("GET".equals(s)){
return GET;
}
if ("POST".equals(s)){
return POST;
}
if ("PUT".equals(s)){
return PUT;
}
if ("HEAD".equals(s)){
return HEAD;
}
// Ã¥ÂÂæ°ä¸ÂÃ¥ÂÂæ³Â
throw new IllegalArgumentException(s);
}
}
public static boolean isComplete(ByteBuffer byteBuffer){
int position = byteBuffer.position() - 4;
if (position < 0){
return false;
}
return byteBuffer.get(position + 0) == '\r'
&& byteBuffer.get(position + 1) == '\n'
&& byteBuffer.get(position + 2) == '\r'
&& byteBuffer.get(position + 2) == '\n';
}
private static Charset ascii = StandardCharsets.US_ASCII;
/**
* æ£åÂÂ表达张ç¨æÂ¥åÂÂå²请æ±ÂæÂ¥æÂÂ
* http 请æ±ÂçÂÂæÂ¥æÂÂæ¯: GET /dir/file HTTP/1.1
* Host: hostname
* 被æ£åÂÂ表达å¼ÂÃ¥ÂÂå²以åÂÂ:
* group[1] = "GET"
* group[2] = "/dir/file"
* group[3] = "1.1"
* group[4] = "hostname"
*/
private static Pattern requestPattern
= Pattern.compile("\\A([A-Z]+) +([^ ]+) +HTTP/([0-9\\.]+)$"
+ ".*^Host: ([^ ]+)$.*\r\n\r\n\\z",
Pattern.MULTILINE | Pattern.DOTALL);
public static Request parse(ByteBuffer byteBuffer) throws RequestException {
// byte to char
CharBuffer charBuffer = ascii.decode(byteBuffer);
Matcher matcher = requestPattern.matcher(charBuffer);
// æªå¹éÂ
Â
if (matcher.matches()){
throw new RequestException();
}
Action a;
try {
a = Action.parse(matcher.group(1));
}catch (IllegalArgumentException e){
throw new RequestException();
}
URI u = null;
try {
u = new URI("http://" + matcher.group(4) + matcher.group(2));
}catch (URISyntaxException e){
throw new RequestException(e);
}
return new Request(a,u,matcher.group(3));
}
}
è¿ÂéÂÂæÂÂ们çÂÂä¸Âä¸Âä¸Â个æÂ¥æÂÂ被å¤ÂçÂÂçÂÂè¿Âç¨Âï¼Âé¦Âå ÂæÂÂ们å°ÂByte转为charï¼Âç¶åÂÂç¨æ£åÂÂ表达å¼Âå°Âæ°æ®è¿Âè¡ÂÃ¥ÂÂå²ï¼Âå¦ÂæÂÂÃ¥ÂÂæÂÂ们设å®ÂçÂÂæ£åÂÂ表达å¼Âä¸Âå¹é Âï¼ÂÃ¥ÂÂæÂÂåº解æÂÂå¼Â常ï¼Âå¦ÂæÂÂ解æÂÂæ£常ï¼Âé£ä¹Âä»Â解æÂÂçÂÂæ°æ®ä¸Â解æÂÂ请æ±Âæ¹å¼Âï¼Âå¦ÂæÂÂä¸Âæ¯æÂÂ们æ¯æÂÂçÂÂ请æ±Âæ¹å¼Âï¼ÂÃ¥ÂÂæ ·ä¹ÂæÂÂåº解æÂÂå¼Â常ãÂÂ解æÂÂ请æ±Âæ¹å¼Âæ£常æÂÂ们ç¨解æÂÂå°çÂÂä¿¡æ¯æÂ¥æÂÂ建URI对象ãÂÂ解æÂÂ失败åÂÂæ ·æÂÂ400ãÂÂæÂÂÃ¥ÂÂè¿ÂÃ¥ÂÂä¸Â个Request对象ãÂÂ解æÂÂå®ÂäºÂ请æ±Âï¼ÂæÂÂ们å¦Âä½Âç»ÂÃ¥ÂÂåºÂï¼Âè¿Âä¹Âå°±æ¯Replyç±»æ¿æÂ¥çÂÂå·¥ä½ÂãÂÂ
Reply
ä¸Â个åÂÂåºÂé¦Âå ÂæÂÂÃ¥ÂÂåºÂç ÂãÂÂÃ¥ÂÂåºÂå 容ï¼Âç¶åÂÂè¾ å©æÂÂ们ç»ÂÃ¥ÂÂåºÂ头ï¼Âé£è¿Â个è¿Â个ç»Â件ï¼ÂåºÂ该堷å¤Âä»Âä¹Âæ ·çÂÂÃ¥ÂÂè½å¢ï¼Âé¦Âå Âæ¯辠å©æÂÂ们å åÂÂåºÂ头ï¼ÂæÂÂ以è¿Â个类éÂÂé¢æÂÂä¸Â个headersæ¹æ³Âï¼Âæ¥辠å©æÂÂ们å 请æ±Â头ãÂÂ请æ±Âæ Â头éÂÂé¢è¿ÂæÂÂä¸Â个ç¶æÂÂç¼Âç Âå¼å¾ÂæÂÂ们注æÂÂï¼Â说çÂÂç¶æÂÂç¼Âç Âï¼ÂÃ¥ÂÂä½ÂÃ¥ÂÂå¦å¯è½è¿Âæ¯ä¸Â大çÂÂ解@æÂÂ们ç´æÂ¥çÂÂå¾:
è¿Â个ç¶æÂÂ代ç Âä¹Âæ¯éÂÂè¦ÂæÂÂ们çÂÂServeréÂÂè¦ÂÃ¥ÂÂåºÂçÂÂï¼Âä¸Â个æ¯httpç¶æÂÂç Âï¼Âå¦ä¸Â个æ¯æÂÂè¿°ï¼Âè¿ÂéÂÂæÂÂç¨类æÂ¥æÂÂè¿°ç¶æÂÂ代ç Âï¼Âè¿Â个类æÂÂå½åÂÂ为Codeï¼Âè¿Âæ¯æÂÂÃ¥ÂÂçÂÂÃ¥ÂÂÃ¥ÂÂï¼Âä½ å¯以å½åÂÂ为StatusCodeï¼Âè¿Â个StatusCode æ¾置äºÂä¸ÂäºÂ常ç¨çÂÂç¶æÂÂ代ç Âï¼ 200ãÂÂ400ãÂÂ404ãÂÂ405ãÂÂæÂÂ以æÂÂ们çÂÂReplyéÂÂé¢éÂÂè¦ÂæÂÂä¸Â个Codeç±»åÂÂçÂÂæÂÂÃ¥ÂÂÃ¥ÂÂéÂÂï¼Âä¸Â个HTTP请æ±Âï¼ÂæÂÂÃ¥ÂÂåºÂæ Â头åÂÂÃ¥ÂÂåºÂä½Âï¼ÂÃ¥ÂÂåºÂä½ÂéÂÂæ¯æ¾æÂÂ们åÂÂéÂÂç»Â客æ·端çÂÂå 容ãÂÂæÂÂ以æÂÂ们è¿ÂéÂÂè¿ÂéÂÂè¦ÂæÂÂä¸Â个åÂÂåºÂä½ÂçÂÂæÂÂÃ¥ÂÂÃ¥ÂÂéÂÂï¼ÂæÂÂ们ä¹ÂçÂ¥éÂÂHTTPæ¯æÂÂÃ¥ÂÂç§ÂÃ¥ÂÂæ ·çÂÂæ¶Âæ¯类åÂÂï¼Âæ¯Âå¦ÂhtmlãÂÂxmlçÂÂçÂÂï¼Âé¤äºÂç±»åÂÂä¹Âå¤Âï¼Âè¿ÂéÂÂè¦ÂÃ¥ÂÂè¯Â客æ·端çÂÂå 容é¿度ãÂÂæÂÂ们åÂÂéÂÂå 容çÂÂæ¶åÂÂæÂÂ纵çÂÂæ¯åÂÂ符æÂÂæÂÂæÂÂ们çÂÂæÂ¥å£éÂÂé¢è¿ÂéÂÂè¦ÂæÂÂä¸Â个æ¹æ³ÂæÂ¥å°Âå 容转ç Â, æÂÂ们åÂÂé¢è¿ÂéÂÂè¦ÂÃ¥ÂÂåºÂæÂÂ件å 容ï¼ÂæÂÂ以æÂ¥å£éÂÂé¢è¿ÂéÂÂè¦ÂæÂÂä¸Â个éÂÂæ¾èµÂæºÂçÂÂæ¹æ³ÂãÂÂè¿ÂéÂÂæÂÂéÂÂæ©ç¨æÂ¥å£æÂ¥æ½象è¡Â为ï¼ÂÃ¥ÂÂéÂÂçÂÂæ¶åÂÂå°±è½使ç¨ä¸Âç»Âæ¹æ³Âï¼ÂæÂÂ建起æÂ¥æ´为ç®ÂÃ¥ÂÂãÂÂæÂÂ认为转ç Âï¼ÂÃ¥ÂÂéÂÂï¼ÂéÂÂæ¾èµÂæºÂåºÂå½Âå¨ä¸Â个æÂ¥å£éÂÂé¢ï¼ÂæÂÂ们å§Âä¸Âå½åÂÂ为Sendableï¼Â
public interface Sendable {
void prepare() throws IOException;
boolean send(ChannelIO channelIO);
void release();
}
èÂÂÃ¥ÂÂåºÂå 容类åÂÂÃ¥ÂÂé¿度ä¸ÂåºÂ该æ¾å¨åÂÂéÂÂæÂ¥å£éÂÂé¢ï¼ÂæÂÂ建模çÂÂæÂÂè·¯æ¯æÂÂ个对象类åÂÂæÂÂä¸ÂÃ¥ÂÂçÂÂÃ¥ÂÂåºÂç±»åÂÂÃ¥ÂÂ计ç®Âé¿度æ¹æ³Âï¼ÂèÂÂä¸Âé½è½åÂÂéÂÂåºå»ï¼ÂæÂÂ以æÂÂè¿ÂéÂÂ设计çÂÂæ¯å®Âé å 容æÂ¥å£继æ¿SendableæÂ¥å£:
public interface Content extends Sendable {
String type();
long length();
}
æÂÂ们è¿ÂéÂÂå®Âç°ä¸Â个æÂÂæ¬类åÂÂï¼ÂæÂÂ们å§Âä¸Âå°Âå ¶å½åÂÂ为StringContentï¼ÂÃ¥ÂÂ符串形å¼ÂçÂÂÃ¥ÂÂåºÂç±»åÂÂæÂÂÃ¥ÂÂç§ÂÃ¥ÂÂæ ·çÂÂï¼ÂæÂÂ以æÂÂ们è¿ÂéÂÂæ¯éÂÂè¦Âå¨StringContentéÂÂé¢æ¾置ä¸Â个è¿Âæ ·ä¸Â个æÂÂÃ¥ÂÂÃ¥ÂÂéÂÂï¼Âå®Âé å 容ä¹Âæ¯ç±å¤Âé¨传堥ï¼Âä¼ å ¥çÂÂå 容æÂÂç»Âè¿Âæ¯éÂÂè¦ÂéÂÂè¿ÂByteBufferè¿ÂÃ¥ÂÂç»Âè°Âç¨è ï¼ÂæÂÂ以è¿ÂéÂÂè¿Âæ¯éÂÂè¦Âä¸Â个ByteBufferä¸Â个æÂÂÃ¥ÂÂÃ¥ÂÂéÂÂãÂÂè¿ÂéÂÂæÂÂé å½æ°æÂÂ们æ¾置ä¸Â个ï¼Â第ä¸Â个æ¯å 容åÂÂç±»åÂÂé½ç±å¤Âé¨传堥ï¼Â第äºÂ个æ¯ç±å¤Âé¨传堥åÂÂåºÂå 容ï¼ÂÃ¥ÂÂåºÂå 容类åÂÂåºå®Â为text/plainã 第ä¸Â个æ¯ä¸ÂæÂ¥åÂÂæ¯æÂÂçÂÂç±»åÂÂï¼Âè¿ÂéÂÂæÂÂ们æÂ¥æ¶çÂÂÃ¥ÂÂæ°æ¯ExceptionãÂÂå¨è¿Âç§ÂæÂÂ导æÂÂæ³ä¸ÂæÂÂ们çÂÂStringContentå¦Âä¸ÂæÂÂ示:
public class StringContent implements Content{
private String type; // MIME type
private String content;
private ByteBuffer byteBuffer;
private static final Charset ascii = StandardCharsets.US_ASCII;
StringContent(CharSequence c, String t) {
content = c.toString();
type = t + "; charset=iso-8859-1";
}
StringContent(CharSequence c) {
this(c, "text/plain");
}
StringContent(Exception x) {
StringWriter sw = new StringWriter();
x.printStackTrace(new PrintWriter(sw));
type = "text/plain; charset=iso-8859-1";
content = sw.toString();
}
@Override
public String type() {
return type;
}
@Override
public long length() {
return byteBuffer.remaining();
}
@Override
public void prepare() throws IOException {
encode();
byteBuffer.rewind();
}
private void encode() {
if (byteBuffer == null){
byteBuffer = ascii.encode(CharBuffer.wrap(content));
}
}
@Override
public boolean send(ChannelIO channelIO) throws IOException {
if (byteBuffer == null)
throw new IllegalStateException();
channelIO.write(byteBuffer);
return byteBuffer.hasRemaining();
}
/**
* è¿Âæ¯个空æ¹æ³Â
* Ã¥ÂÂé¢åªæ¯为äºÂç»Âä¸Âè°Âç¨
*/
@Override
public void release() {
}
}
æÂÂ们æÂ¥çÂÂÃ¥ÂÂå°Replyï¼ÂReplyéÂÂé¢æÂÂCodeãÂÂContentï¼Âè¿ÂæÂÂä¸Â个辠å©æÂÂ建请æ±Â头çÂÂï¼ÂæÂÂå°ÂÃ¥ÂÂéÂÂæ°æ®çÂÂä¹Âæ¾置å¨è¿Â个æ¹æ³ÂéÂÂé¢ï¼ÂæÂÂ以Replyä¹Âå®Âç°äºÂSendableæÂ¥å£, è´Âè´£å°Âæ°æ®åÂÂéÂÂç»Â客æ·端, æÂÂ以Replyå¦Âä¸ÂæÂÂ示:
public class Reply implements Sendable {
static class Code{
private int number;
private String description;
public Code(int number, String description) {
this.number = number;
this.description = description;
}
static Code OK = new Code(200,"OK");
static Code BAD_REQUEST = new Code(400,"Bad Request");
static Code NOT_FOUND = new Code(404,"Not Found");
static Code METHOD_NOT_ALLOWED = new Code(405,"Method Not Allowed");
}
private Code code;
private Content content;
private ByteBuffer headerBuffer;
private static String CRLF = "\r\n";
private static Charset ascii = Charset.forName("US-ASCII");
public Reply(Code code, Content content) {
this.code = code;
this.content = content;
}
/**
* è¿Â个æ¹æ³Âè´Â责添å 请æ±Â头
* @return
*/
private ByteBuffer headers(){
CharBuffer cb = CharBuffer.allocate(1024);
cb.put("HTTP/1.0 ").put(code.toString()).put(CRLF);
cb.put("Server: niossl/0.1").put(CRLF);
cb.put("Content-type: ").put(content.type()).put(CRLF);
cb.put("Content-length: ")
.put(Long.toString(content.length())).put(CRLF);
cb.put(CRLF);
cb.flip();
return ascii.encode(cb);
}
@Override
public void prepare() throws IOException {
content.prepare();
headerBuffer = headers();
}
@Override
public boolean send(ChannelIO channelIO) throws IOException {
// Ã¥Â
ÂÃ¥ÂÂ请æ±Â头
if (headerBuffer.hasRemaining()){
if (channelIO.write(headerBuffer) <= 0)
return true;
}
// Ã¥ÂÂÃ¥ÂÂÃ¥ÂÂåºÂÃ¥ÂÂ
容
if (content.send(channelIO))
return true;
return false;
}
@Override
public void release() {
content.release();
}
}
ç°å¨å¼Âå§Âç»ÂÃ¥ÂÂ请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂ
ç°å¨æÂÂ们请æ±ÂÃ¥ÂÂÃ¥ÂÂåºÂç»Â件é½é½Âæ´»äºÂï¼Âç°å¨就å¯以å°Âè¿Â两个ç»Â件ç»ÂÃ¥ÂÂèµ·æ¥干活äºÂï¼Âè¿ÂéÂÂæÂÂå¤ÂçÂÂçÂÂæµÂç¨Â为æÂ¥æ¶æ°æ®ãÂÂ解æÂÂæ°æ®ãÂÂæÂÂ建åÂÂåºÂãÂÂÃ¥ÂÂéÂÂæ°æ®ãÂÂè¿Â个ç»ÂÃ¥ÂÂæµÂç¨Â类就æ¯æÂÂç §è¿Â个æµÂç¨ÂæÂ¥åÂÂçÂÂï¼ å¦Âä¸ÂæÂÂ示:
public class RequestServicer implements Runnable {
private ChannelIO channelIO;
public RequestServicer(ChannelIO channelIO) {
this.channelIO = channelIO;
}
private void service() throws IOException {
ByteBuffer byteBuffer = receive(); // æÂ¥æ¶æ°æ®
Request request = null;
Reply reply = null;
try {
request = Request.parse(byteBuffer);
} catch (RequestException e) {
reply = new Reply(Reply.Code.BAD_REQUEST, new StringContent(e));
}
// 说æÂÂæ£常解æÂÂ
if (reply == null) {
reply = build(request); // æÂÂ建åÂÂå¤Â
}
reply.prepare();
do {} while (reply.send(channelIO)); // Send
}
@Override
public void run() {
try {
service();
} catch (IOException e) {
e.printStackTrace();
}
}
ByteBuffer receive() throws IOException {
for (; ; ) {
int read = channelIO.read();
ByteBuffer bb = channelIO.getReadBuf();
if ((read < 0) || (Request.isComplete(bb))) {
bb.flip();
return bb;
}
}
}
Reply build(Request rq) throws IOException {
Reply rp = null;
Request.Action action = rq.action();
if ((action != Request.Action.GET)) {
rp = new Reply(Reply.Code.METHOD_NOT_ALLOWED,
new StringContent(rq.toString()));
rp.prepare();
return rp;
}
rp = new Reply(Reply.Code.OK,
new StringContent("hello world"));
rp.prepare();
return rp;
}
}
å¨BlockingServeréÂÂé¢ç»ÂÃ¥ÂÂ
public class BlockingServer extends Server{
private static final ExecutorService POOL = Executors.newFixedThreadPool(8);
public BlockingServer(int port, int backlog, boolean secure) throws IOException {
super(port, backlog, secure);
}
@Override
protected void runServer() throws IOException {
SocketChannel socketChannel = serverSocketChannel.accept();
ChannelIO channleIO = ChannelIO.getInstance(socketChannel, true);
RequestServicer requestServicer = new RequestServicer(channleIO);
POOL.submit(requestServicer);
}
}
è¿Âè¡Â代ç Âï¼Âå¨æµÂè§Âå¨éÂÂé¢访é®localhost:8080ï¼Âå°±è½çÂÂå°helloWorldäºÂï¼Âä½Âæ¯æÂÂ们çÂÂHTTPæÂÂå¡å¨ä»Âç¶åÂÂå¨ä¸ÂäºÂé®é¢Âï¼Âä½ ä¼ÂÃ¥ÂÂç°第ä¸Â次åÂÂåºÂ请æ±Âå¾Âå¿«ï¼Â第äºÂ次åÂÂåºÂ请æ±Âå°±å¾Âæ ¢ï¼Âè¿Âæ¯代ç ÂæÂÂé®é¢Âï¼ÂæÂÂ们åÂÂé¢æ¾çÂÂä¼ÂÃ¥ÂÂãÂÂ
æ»ç»Âä¸Âä¸Â
è¿Âç¯ÂæÂÂç« çÂÂÃ¥ÂÂä½Âæ¶é´è¿Âè¿Âæ¯Âèª己æ³象çÂÂæ¶é´é¿ï¼Âæ¾¥æ³å·个æÂÂï¼Âä¸Âå¨ä»Âç»Â计ç®Âæºç½Âç»ÂçÂÂæ¼ÂÃ¥ÂÂÃ¥ÂÂç½Âç»Âç¼Âç¨ÂçÂÂåºæ¬æ¦Â念ï¼Âä½Âæ¯åÂÂæ³åÂÂå°轻éÂÂ级çÂÂé 读ä½ÂéªÂï¼Âå°±åÂÂéÂÂæ°梳çÂÂäºÂä¸Âä¸Âèª己对ç½Âç»ÂçÂÂçÂÂ解ï¼Âç¿»äºÂç¿»èª己以åÂÂçÂÂæÂÂç« ï¼ÂÃ¥ÂÂç°èª己对ç½Âç»ÂçÂÂçÂÂ解ï¼Âä»Âä¸Âå±Âå°ä¸Âå±ÂçÂÂæ¼ÂÃ¥ÂÂè¿Âä¸Âå±Âè¿Âæ¯å¾Â模ç³Âï¼Â幸è¿ÂçÂÂæ¯å¨çÂ¥ä¹ÂçÂÂå°äºÂä¸Âç¯Â讲解ç½Âç»ÂÃ¥ÂÂå±ÂÃ¥ÂÂå²çÂÂæÂÂç« , è§ÂÃ¥ÂÂèÂÂæÂÂæ¡£[1]ãÂÂæ¬ç¯Âä¹Âæ¯为åÂÂé¢çÂÂç¨JavaFXÃ¥ÂÂç®ÂÃ¥ÂÂéÂÂ信软件çÂÂéºå«ï¼Âæ¿åÂÂå¯åÂÂãÂÂæ¬ç¯Âå®ÂæÂÂçÂÂHTTPæÂÂå¡å¨æ¯æ¯Âè¾ÂÃ¥ÂÂ级çÂÂï¼Âå°±æ¯访é®localhost:8080, å¨æµÂè§Âå¨ä¸Âä¼Âè¿ÂÃ¥ÂÂhello worldï¼ÂÃ¥ÂÂé¢ä¼ÂÃ¥ÂÂ补堠ä¸ÂæÂÂ件类åÂÂï¼Â使ç¨é¶æ·è´ÂæÂÂæ¯æÂ¥å®Âç°ãÂÂÃ¥ÂÂé¢åÂÂç¨NIOãÂÂNettyÃ¥ÂÂå®Âç°ä¸ÂéÂÂãÂÂå Âå»å®Âè·µï¼ÂæÂÂäºÂå®Âè·µåÂÂÃ¥ÂȍÂÂNettyçÂÂæºÂç Âï¼ÂÃ¥ÂÂæÂÂå ¶åÂÂçÂÂãÂÂÃ¥ÂÂæ¬ç¯ÂçÂÂæ¶åÂÂï¼ÂæÂÂä¹Âå¨æÂÂæÂÂè¯ÂçÂÂÃ¥ÂȏÂÂå¼Âè¿ÂÃ¥ÂȾÂÂÃ¥ÂÂå¼ÂçÂÂÃ¥ÂÂæ³Âï¼ÂæÂÂç¨çÂÂæ¯æÂÂÃ¥ÂÂ欢æÂÂç§Â书çÂÂé£Âæ ¼ï¼ÂÃ¥ÂÂå¾æÂÂ读è å½ÂæÂÂæÂÂÃ¥ÂÂï¼Âå¹³çÂÂ对徠ï¼Âå¨Âå¨Âè°Âå¿Âï¼ÂæÂÂä¸Âä» åÂÂè¯ÂäºÂåªäºÂæ¯对çÂÂï¼Âè¿ÂÃ¥ÂÂçÂ¥äºÂæÂÂçÂÂæ¢索è¿Âç¨Âï¼Âå°±æ¯æÂÂæ¯å¦Âä½Âå¾Âåºè¿Â个ç»Â论çÂÂï¼ÂÃ¥ÂÂHTTPæÂÂå¡å¨çÂÂæ¶åÂÂï¼ÂæÂÂèª认为æ¯Âè¾ÂçÂÂæÂÂäºÂï¼Âä½ÂçÂÂæ£å¨ç¬ÂçÂÂæ¶åÂÂæÂÂÃ¥ÂÂç°ï¼Âèª己æÂÂäºÂå°æ¹è¿Âæ¯çÂÂ解ä¸Â对ï¼Âé¢ÂæÂÂç¹纸ä¸Âå¾ÂæÂ¥ç»Âè§Âæµ ï¼Âç»ÂçÂ¥æ¤äºÂè¦Â躬è¡ÂçÂÂæÂÂè§ÂãÂÂæÂÂå¨ç»Âåº设计çÂÂæ¶åÂÂï¼ÂæÂȾ¯å Âç»Âåºç®æ Âï¼ÂÃ¥ÂÂç»ÂåºæÂÂ为ä»Âä¹Âè¦Âè¿Âä¹Â设计ï¼Â诸åÂÂå®Âå ¨å¯以åÂÂåºè·ÂæÂÂå®Âå ¨ä¸ÂÃ¥ÂÂçÂÂ代ç Âï¼ÂÃ¥ÂÂçÂÂæ¬质çÂÂä¸Â西æÂÂé½åÂÂè¯ÂäºÂ诸åÂÂãÂÂ
æ¬ç¯ÂåºæÂŒÂÂèÂÂçÂÂäºÂJDK 8çÂÂdemoï¼ÂJDK 8ç»ÂäºÂæ°ç¹æ§çÂÂ示ä¾Âï¼ÂæÂÂçÂÂäºÂè¿Â个代ç Âè§Âå¾Âæ¯Âè¾ÂæÂÂ趣ï¼Âå°±è§Âå¾Â以èª己çÂÂæ¹å¼Âæ¥解读ä¸Âä¸Âï¼Âæ¬身é¢Âå Â设å®ÂçÂÂç®æ ÂÃ¥ÂÂæ¯没æÂÂè¿Âä¹Âå¤Âï¼ÂÃ¥ÂÂçÂÂÃ¥ÂÂçÂÂå 容就åÂÂå¾ÂåºÂ大äºÂèµ·æÂ¥ï¼Âæ¾¥è¿ÂæÂÂç®Âä»Âç»Âä¸Âä¸Âé¢åÂÂ对象设计ï¼ÂæÂ¥å£çÂÂå¨æºï¼Âé½糠åÂÂå¨æ¬ç¯Âæ³æÂ¥æ¯Âè¾Â大äºÂï¼Â太大çÂÂå 容ï¼Âæ´ä½Âä¸Âå 容似ä¹Âä¹Âä¸Âè¿Âè´¯ï¼ÂÃ¥ÂÂé¢ç¨NIOéÂÂÃ¥ÂÂçÂÂæ¶åÂÂï¼Âä¼Âå°Âè¯Âå°Âè¿ÂäºÂè¿Âè¡ÂÃ¥ÂÂæÂÂï¼Âå¢Âå ä¸Âä¸Âé 读ä½ÂéªÂãÂÂ
强è°Âä¸Âä¸Âï¼Âå ³äºÂç½Âç»ÂçÂÂæ¼ÂÃ¥ÂÂï¼Â主è¦ÂÃ¥ÂÂèÂÂçÂÂæ¯åÂÂèÂÂèµÂæÂÂ[1]ï¼Âå ³äºÂç½Âç»Âæ¼ÂÃ¥ÂÂçÂÂè¿Âæ¹é¢åÂÂçÂÂçÂÂä¸ÂéÂÂãÂÂ
Ã¥ÂÂèÂÂèµÂæÂÂ
[1] æÂÂ亠IP å°åÂÂï¼Â为ä»Âä¹Âè¿Âè¦Âç¨ MAC å°åÂÂï¼ www.zhihu.com/question/21â¦
[2] java socketç¼Âç¨Âä¸ÂÃ¥ÂÂæ°backlogçÂÂå«ä¹Â
[3] TCP Ã¥ÂÂè®®ç®Âä» www.ruanyifeng.com/blog/2017/0â¦
[4] HTTP æ¶Âæ¯ç»ÂæÂÂçÂÂæ Âå¿ www.jtr109.com/posts/http-â¦
[5] 浠堥深åºè°Âè° HTTP Ã¥ÂÂåºÂæÂÂÃ¥ÂÂï¼ÂCRLF Injectionï¼ÂæÂȌ»ï¼Âä¸Âï¼ xz.aliyun.com/t/9707