# NET
## DES
### ç½ç»ç¼ç¨
ç½ç»ç¼ç¨ï¼å°±æ¯å¨ä¸å®çåè®®ä¸ï¼å®ç°ä¸¤å°è®¡ç®æºçéä¿¡çææ¯
éä¿¡ä¸å®æ¯åºäºè½¯ä»¶ç»æå®ç°ç:
* C/S ç»æ ï¼å
¨ç§°ä¸º Client/Server ç»æï¼æ¯æå®¢æ·ç«¯åæå¡å¨ç»æï¼å¸¸è§ç¨åºæ QQãIDEA ç软件
* B/S ç»æ ï¼å
¨ç§°ä¸º Browser/Server ç»æï¼æ¯ææµè§å¨åæå¡å¨ç»æ
ä¸¤ç§æ¶æåæä¼å¿ï¼ä½æ¯æ 论åªç§æ¶æï¼é½ç¦»ä¸å¼ç½ç»çæ¯æ
ç½ç»éä¿¡çä¸è¦ç´ ï¼
1. åè®®ï¼è®¡ç®æºç½ç»å®¢æ·ç«¯ä¸æå¡ç«¯éä¿¡å¿
须约å®åå½¼æ¤éµå®çéä¿¡è§åï¼HTTPãFTPãTCPãUDPãSMTP
2. IP å°åï¼äºèç½åè®®å°åï¼Internet Protocol Addressï¼ï¼ç¨æ¥ç»ä¸ä¸ªç½ç»ä¸çè®¡ç®æºè®¾å¤åå¯ä¸çç¼å·
* IPv4ï¼4 个åèï¼32 ä½ç»æï¼192.168.1.1
* IPv6ï¼å¯ä»¥å®ç°ä¸ºææè®¾å¤åé
IPï¼128 ä½
* ipconfigï¼æ¥çæ¬æºç IP
* ping æ£æ¥æ¬æºä¸æä¸ª IP æå®çæºå¨æ¯å¦èéï¼æè
è¯´æ¯æ£æµå¯¹æ¹æ¯å¦å¨çº¿ã
* ping ç©ºæ ¼ IPå°å ï¼ping 220.181.57.216ï¼ping www.baidu.com
ç¹æ®çIPå°åï¼ æ¬æºIPå°åï¼**127.0.0.1 == localhost**ï¼åç¯æµè¯
3. 端å£ï¼ç«¯å£å·å°±å¯ä»¥å¯ä¸æ è¯è®¾å¤ä¸çè¿ç¨ï¼åºç¨ç¨åºï¼ã端å£å·æ¯ç¨ä¸¤ä¸ªåèè¡¨ç¤ºçæ´æ°ï¼åå¼èå´æ¯ 0-65535ï¼0-1023 ä¹é´ç端å£å·ç¨äºä¸äºç¥åçç½ç»æå¡ååºç¨æ®éçåºç¨ç¨åºéè¦ä½¿ç¨ 1024 以ä¸ç端å£å·ãå¦æç«¯å£å·è¢«å¦å¤ä¸ä¸ªæå¡æåºç¨æå ç¨ï¼ä¼å¯¼è´å½åç¨åºå¯å¨å¤±è´¥ï¼æ¥åºç«¯å£è¢«å ç¨å¼å¸¸
å©ç¨**åè®®+IP å°å+端å£å·**ä¸å
ç»åï¼å°±å¯ä»¥æ è¯ç½ç»ä¸çè¿ç¨äºï¼é£ä¹è¿ç¨é´çéä¿¡å°±å¯ä»¥å©ç¨è¿ä¸ªæ è¯ä¸å
¶å®è¿ç¨è¿è¡äº¤äº
åèè§é¢ï¼https://www.bilibili.com/video/BV1kT4y1M7vt
****
### éä¿¡åè®®
ç½ç»éä¿¡åè®®ï¼å¯¹è®¡ç®æºå¿
é¡»éµå®çè§åï¼åªæéµå®è¿äºè§åï¼è®¡ç®æºä¹é´æè½è¿è¡éä¿¡
éä¿¡**æ¯è¿ç¨ä¸è¿ç¨ä¹é´çéä¿¡**ï¼ä¸æ¯ä¸»æºä¸ä¸»æºä¹é´çéä¿¡
TCP/IPåè®®ï¼ä¼ è¾æ§å¶åè®® (Transmission Control Protocol)
ä¼ è¾æ§å¶åè®® TCPï¼Transmission Control Protocolï¼æ¯é¢åè¿æ¥çï¼æä¾å¯é 交ä»ï¼ææµéæ§å¶ï¼æ¥å¡æ§å¶ï¼æä¾å
¨åå·¥éä¿¡ï¼é¢ååèæµï¼æ¯ä¸æ¡ TCP è¿æ¥åªè½æ¯ç¹å¯¹ç¹çï¼ä¸å¯¹ä¸ï¼
* å¨éä¿¡ä¹åå¿
须确å®å¯¹æ¹å¨çº¿å¹¶ä¸è¿æ¥æåæå¯ä»¥éä¿¡
* ä¾å¦ä¸è½½æä»¶ãæµè§ç½é¡µçï¼è¦æ±å¯é ä¼ è¾ï¼
ç¨æ·æ°æ®æ¥åè®® UDPï¼User Datagram Protocolï¼æ¯æ è¿æ¥çï¼å°½æå¤§å¯è½äº¤ä»ï¼ä¸å¯é ï¼æ²¡ææ¥å¡æ§å¶ï¼é¢åæ¥æï¼æ¯æä¸å¯¹ä¸ãä¸å¯¹å¤ãå¤å¯¹ä¸åå¤å¯¹å¤ç交äºéä¿¡
* ç´æ¥åæ¶æ¯ç»å¯¹æ¹ï¼ä¸ç®¡å¯¹æ¹æ¯å¦å¨çº¿ï¼åæ¶æ¯åä¹ä¸éè¦ç¡®è®¤
* æ 线ï¼è§é¢ä¼è®®ï¼éè¯ï¼ï¼æ§è½å¥½ï¼å¯è½ä¸¢å¤±ä¸äºæ°æ®
****
### Java模å
ç¸å
³æ¦å¿µï¼
* 忥ï¼å½å线ç¨è¦èªå·±è¿è¡æ°æ®ç读åæä½ï¼èªå·±å»é¶è¡åé±ï¼
* 弿¥ï¼å½å线ç¨å¯ä»¥å»åå
¶ä»äºæ
ï¼å§æå«äººæ¿é¶è¡å¡å°é¶è¡åé±ï¼ç¶åç»ä½ ï¼
* é»å¡ï¼å¨æ°æ®æ²¡æçæ
åµä¸ï¼è¿æ¯è¦ç»§ç»çå¾
çè¯»ï¼æéçå¾
ï¼
* éé»å¡ï¼å¨æ°æ®æ²¡æçæ
åµä¸ï¼ä¼å»åå
¶ä»äºæ
ï¼ä¸æ¦æäºæ°æ®åæ¥è·åï¼æå°å款ï¼å个å·ï¼ç¶åå卿¤
åä¸åå
¶å®äºï¼çå·å¹¿æä¼éç¥ä½ åçï¼
Java ä¸çé信模å:
1. BIO è¡¨ç¤ºåæ¥é»å¡å¼éä¿¡ï¼æå¡å¨å®ç°æ¨¡å¼ä¸ºä¸ä¸ªè¿æ¥ä¸ä¸ªçº¿ç¨ï¼å³å®¢æ·ç«¯æè¿æ¥è¯·æ±æ¶æå¡å¨ç«¯å°±éè¦å¯å¨ä¸ä¸ªçº¿ç¨è¿è¡å¤çï¼å¦æè¿ä¸ªè¿æ¥ä¸åä»»ä½äºæ
ä¼é æä¸å¿
è¦ç线ç¨å¼éï¼å¯ä»¥éè¿çº¿ç¨æ± æºå¶æ¹å
忥é»å¡å¼æ§è½æå·®ï¼å¤§é线ç¨ï¼å¤§éé»å¡
2. ä¼ªå¼æ¥éä¿¡ï¼å¼å
¥çº¿ç¨æ± ï¼ä¸éè¦ä¸ä¸ªå®¢æ·ç«¯ä¸ä¸ªçº¿ç¨ï¼å®ç°çº¿ç¨å¤ç¨æ¥å¤çå¾å¤ä¸ªå®¢æ·ç«¯ï¼çº¿ç¨å¯æ§
é«å¹¶å䏿§è½è¿æ¯å¾å·®ï¼çº¿ç¨æ°éå°ï¼æ°æ®ä¾ç¶æ¯é»å¡çï¼æ°æ®æ²¡ææ¥çº¿ç¨è¿æ¯è¦çå¾
3. NIO 表示**忥éé»å¡ IO**ï¼æå¡å¨å®ç°æ¨¡å¼ä¸ºè¯·æ±å¯¹åºä¸ä¸ªçº¿ç¨ï¼å®¢æ·ç«¯åéçè¿æ¥ä¼æ³¨åå°å¤è·¯å¤ç¨å¨ä¸ï¼å¤è·¯å¤ç¨å¨è½®è¯¢å°è¿æ¥æ I/O è¯·æ±æ¶æå¯å¨ä¸ä¸ªçº¿ç¨è¿è¡å¤ç
å·¥ä½åçï¼1 个主线ç¨ä¸é¨è´è´£æ¥æ¶å®¢æ·ç«¯ï¼1 个线ç¨è½®è¯¢ææç客æ·ç«¯ï¼åæ¥äºæ°æ®æä¼å¼å¯çº¿ç¨å¤ç
忥ï¼çº¿ç¨è¿è¦ä¸æçæ¥æ¶å®¢æ·ç«¯è¿æ¥ï¼ä»¥åå¤çæ°æ®
éé»å¡ï¼å¦æä¸ä¸ªç®¡éæ²¡ææ°æ®ï¼ä¸éè¦çå¾
ï¼å¯ä»¥è½®è¯¢ä¸ä¸ä¸ªç®¡éæ¯å¦ææ°æ®
4. AIO è¡¨ç¤ºå¼æ¥éé»å¡ IOï¼AIO å¼å
¥å¼æ¥ééçæ¦å¿µï¼éç¨äº Proactor 模å¼ï¼ææçè¯·æ±æå¯å¨çº¿ç¨ï¼ç¹ç¹æ¯å
ç±æä½ç³»ç»å®æåæéç¥æå¡ç«¯ç¨åºå¯å¨çº¿ç¨å»å¤çï¼ä¸è¬éç¨äºè¿æ¥æ°è¾å¤ä¸è¿æ¥æ¶é´è¾é¿çåºç¨
弿¥ï¼æå¡ç«¯çº¿ç¨æ¥æ¶å°äºå®¢æ·ç«¯ç®¡é以å就交ç»åºå±å¤ç IO éä¿¡ï¼çº¿ç¨å¯ä»¥åå
¶ä»äºæ
éé»å¡ï¼åºå±ä¹æ¯å®¢æ·ç«¯ææ°æ®æä¼å¤çï¼æäºæ°æ®ä»¥åå¤ç好éç¥æå¡å¨åºç¨æ¥å¯å¨çº¿ç¨è¿è¡å¤ç
åç§æ¨¡ååºç¨åºæ¯ï¼
* BIO éç¨äºè¿æ¥æ°ç®æ¯è¾å°ä¸åºå®çæ¶æï¼è¯¥æ¹å¼å¯¹æå¡å¨èµæºè¦æ±æ¯è¾é«ï¼å¹¶åå±éäºåºç¨ä¸ï¼ç¨åºç®å
* NIO éç¨äºè¿æ¥æ°ç®å¤ä¸è¿æ¥æ¯è¾çï¼è½»æä½ï¼çæ¶æï¼å¦è天æå¡å¨ï¼å¹¶åå±éäºåºç¨ä¸ï¼ç¼ç¨å¤æï¼JDK 1.4 å¼å§æ¯æ
* AIO éç¨äºè¿æ¥æ°ç®å¤ä¸è¿æ¥æ¯è¾é¿ï¼éæä½ï¼çæ¶æï¼å¦ç¸åæå¡å¨ï¼å
åè°ç¨æä½ç³»ç»åä¸å¹¶åæä½ï¼JDK 1.7 å¼å§æ¯æ
****
## I/O
### IO模å
#### äºç§æ¨¡å
对äºä¸ä¸ªå¥æ¥åä¸çè¾å
¥æä½ï¼ç¬¬ä¸æ¥æ¯çå¾
æ°æ®ä»ç½ç»ä¸å°è¾¾ï¼å½æ°æ®å°è¾¾æ¶è¢«å¤å¶å°å
æ ¸ä¸çæä¸ªç¼å²åºãç¬¬äºæ¥å°±æ¯ææ°æ®ä»å
æ ¸ç¼å²åºå¤å¶å°åºç¨è¿ç¨ç¼å²åº
Linux æäºç§ I/O 模åï¼
- é»å¡å¼ I/O
- éé»å¡å¼ I/O
- I/O å¤ç¨ï¼select å pollï¼
- ä¿¡å·é©±å¨å¼ I/Oï¼SIGIOï¼
- 弿¥ I/Oï¼AIOï¼
äºç§æ¨¡å对æ¯ï¼
* 忥 I/O å
æ¬é»å¡å¼ I/Oãéé»å¡å¼ I/OãI/O å¤ç¨åä¿¡å·é©±å¨ I/O ï¼å®ä»¬ç主è¦åºå«å¨ç¬¬ä¸ä¸ªé¶æ®µï¼éé»å¡å¼ I/O ãä¿¡å·é©±å¨ I/O å弿¥ I/O å¨ç¬¬ä¸é¶æ®µä¸ä¼é»å¡
- 忥 I/Oï¼å°æ°æ®ä»å
æ ¸ç¼å²åºå¤å¶å°åºç¨è¿ç¨ç¼å²åºçé¶æ®µï¼ç¬¬äºé¶æ®µï¼ï¼åºç¨è¿ç¨ä¼é»å¡
- 弿¥ I/Oï¼ç¬¬äºé¶æ®µåºç¨è¿ç¨ä¸ä¼é»å¡
***
#### é»å¡å¼IO
åºç¨è¿ç¨éè¿ç³»ç»è°ç¨ recvfrom æ¥æ¶æ°æ®ï¼ä¼è¢«é»å¡ï¼ç´å°æ°æ®ä»å
æ ¸ç¼å²åºå¤å¶å°åºç¨è¿ç¨ç¼å²åºä¸æè¿åãé»å¡ä¸æå³çæ´ä¸ªæä½ç³»ç»é½è¢«é»å¡ï¼å
¶å®åºç¨è¿ç¨è¿å¯ä»¥æ§è¡ï¼åªæ¯å½åé»å¡è¿ç¨ä¸æ¶è CPU æ¶é´ï¼è¿ç§æ¨¡åç CPU å©ç¨ç伿¯è¾é«
recvfrom() ç¨äº**æ¥æ¶ Socket ä¼ æ¥çæ°æ®ï¼å¹¶å¤å¶å°åºç¨è¿ç¨çç¼å²åº buf ä¸**ï¼æ recvfrom() å½æç³»ç»è°ç¨

***
#### éé»å¡å¼
åºç¨è¿ç¨éè¿ recvfrom è°ç¨ä¸åçå»åå
æ ¸äº¤äºï¼ç´å°å
æ ¸åå¤å¥½æ°æ®ãå¦ææ²¡æåå¤å¥½æ°æ®ï¼å
æ ¸è¿åä¸ä¸ªé误ç ï¼è¿ä¸æ®µæ¶é´åºç¨è¿ç¨åæ§è¡ recvfrom ç³»ç»è°ç¨ï¼å¨ä¸¤æ¬¡åé请æ±çæ¶é´æ®µï¼è¿ç¨å¯ä»¥è¿è¡å
¶ä»ä»»å¡ï¼è¿ç§æ¹å¼ç§°ä¸ºè½®è¯¢ï¼pollingï¼
ç±äº CPU è¦å¤çæ´å¤çç³»ç»è°ç¨ï¼å æ¤è¿ç§æ¨¡åç CPU å©ç¨çæ¯è¾ä½

***
#### ä¿¡å·é©±å¨
åºç¨è¿ç¨ä½¿ç¨ sigaction ç³»ç»è°ç¨ï¼å
æ ¸ç«å³è¿åï¼åºç¨è¿ç¨å¯ä»¥ç»§ç»æ§è¡ï¼çå¾
æ°æ®é¶æ®µåºç¨è¿ç¨æ¯éé»å¡çãå½å
æ ¸æ°æ®åå¤å°±ç»ªæ¶ååºç¨è¿ç¨åé SIGIO ä¿¡å·ï¼åºç¨è¿ç¨æ¶å°ä¹åå¨ä¿¡å·å¤çç¨åºä¸è°ç¨ recvfrom å°æ°æ®ä»å
æ ¸å¤å¶å°åºç¨è¿ç¨ä¸
ç¸æ¯äºéé»å¡å¼ I/O ç轮询æ¹å¼ï¼ä¿¡å·é©±å¨ I/O ç CPU å©ç¨çæ´é«

***
#### IO å¤ç¨
IO å¤ç¨æ¨¡åä½¿ç¨ select æè
poll 彿°çå¾
æ°æ®ï¼select ä¼çå¬æææ³¨å好ç IOï¼**çå¾
å¤ä¸ªå¥æ¥åä¸çä»»ä½ä¸ä¸ªå为å¯è¯»**ï¼çå¾
è¿ç¨ä¼è¢«é»å¡ï¼å½æä¸ªå¥æ¥ååå¤å¥½æ°æ®å为å¯è¯»æ¶ select è°ç¨å°±è¿åï¼ç¶åè°ç¨ recvfrom ææ°æ®ä»å
æ ¸å¤å¶å°è¿ç¨ä¸
IO å¤ç¨è®©å个è¿ç¨å
·æå¤çå¤ä¸ª I/O äºä»¶çè½åï¼å被称为 Event Driven I/Oï¼å³**äºä»¶é©±å¨ I/O**
妿ä¸ä¸ª Web æå¡å¨æ²¡æ I/O å¤ç¨ï¼é£ä¹æ¯ä¸ä¸ª Socket è¿æ¥é½è¦å建ä¸ä¸ªçº¿ç¨å»å¤çï¼å¦æåæ¶æå ä¸ä¸ªè¿æ¥ï¼å°±éè¦å建ç¸åæ°éç线ç¨ãç¸æ¯äºå¤è¿ç¨åå¤çº¿ç¨ææ¯ï¼I/O å¤ç¨ä¸éè¦è¿ç¨çº¿ç¨å建å忢çå¼éï¼ç³»ç»å¼éæ´å°

***
#### 弿¥ IO
åºç¨è¿ç¨æ§è¡ aio_read ç³»ç»è°ç¨ä¼ç«å³è¿åï¼ç»å
æ ¸ä¼ éæè¿°ç¬¦ãç¼å²åºæéãç¼å²åºå¤§å°çãåºç¨è¿ç¨å¯ä»¥ç»§ç»æ§è¡ä¸ä¼è¢«é»å¡ï¼å
æ ¸ä¼å¨æææä½å®æä¹åååºç¨è¿ç¨åéä¿¡å·
弿¥ I/O ä¸ä¿¡å·é©±å¨ I/O çåºå«å¨äºï¼å¼æ¥ I/O çä¿¡å·æ¯éç¥åºç¨è¿ç¨ I/O 宿ï¼èä¿¡å·é©±å¨ I/O çä¿¡å·æ¯éç¥åºç¨è¿ç¨å¯ä»¥å¼å§ I/O

****
### å¤è·¯å¤ç¨
#### select
##### 彿°
Socket 䏿¯æä»¶ï¼åªæ¯ä¸ä¸ªæ è¯ç¬¦ï¼ä½æ¯ Unix æä½ç³»ç»æææä¸è¥¿é½**çä½**æ¯æä»¶ï¼æä»¥ Socket 说æ file descriptorï¼ä¹å°±æ¯ fd
select å
许åºç¨ç¨åºçè§ä¸ç»æä»¶æè¿°ç¬¦ï¼çå¾
ä¸ä¸ªæè
å¤ä¸ªæè¿°ç¬¦æä¸ºå°±ç»ªç¶æï¼ä»è宿 I/O æä½ã
```c
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
```
- fd_set ä½¿ç¨ **bitmap æ°ç»**å®ç°ï¼æ°ç»å¤§å°ç¨ FD_SETSIZE å®ä¹ï¼**åè¿ç¨**åªè½çå¬å°äº FD_SETSIZE æ°éçæè¿°ç¬¦ï¼32 使ºé»è®¤æ¯ 1024 个ï¼64 使ºé»è®¤æ¯ 2048ï¼å¯ä»¥å¯¹è¿è¡ä¿®æ¹ï¼ç¶åéæ°ç¼è¯å
æ ¸
- fd_set æä¸ç§ç±»åçæè¿°ç¬¦ï¼readsetãwritesetãexceptsetï¼å¯¹åºè¯»ãåãå¼å¸¸æ¡ä»¶çæè¿°ç¬¦éå
- n æ¯çæµç socket çæå¤§æ°é
- timeout 为è¶
æ¶åæ°ï¼è°ç¨ select ä¼ä¸ç´**é»å¡**ç´å°ææè¿°ç¬¦çäºä»¶å°è¾¾æè
çå¾
çæ¶é´è¶
è¿ timeout
```c
struct timeval{
long tv_sec; //ç§
long tv_usec; //å¾®ç§
}
```
* timeout == nullï¼çå¾
æ éé¿çæ¶é´
* tv_sec == 0 && tv_usec == 0ï¼è·ååç´æ¥è¿åï¼ä¸é»å¡çå¾
* tv_sec != 0 || tv_usec != 0ï¼çå¾
æå®æ¶é´
- æ¹æ³æåè°ç¨è¿åç»æä¸º**就绪çæä»¶æè¿°ç¬¦ä¸ªæ°**ï¼åºéè¿åç»æä¸º -1ï¼è¶
æ¶è¿åç»æä¸º 0
Linux æä¾äºä¸ç»å®ä¸º fd_set è¿è¡èµå¼æä½ï¼
```c
int FD_ZERO(fd_set *fdset); // å°ä¸ä¸ª fd_set ç±»ååéçææå¼é½ç½®ä¸º 0
int FD_CLR(int fd, fd_set *fdset); // å°ä¸ä¸ª fd_set ç±»ååéç fd ä½ç½®ä¸º 0
int FD_SET(int fd, fd_set *fdset); // å°ä¸ä¸ª fd_set ç±»ååéç fd ä½ç½®ä¸º 1
int FD_ISSET(int fd, fd_set *fdset);// 夿 fd 使¯å¦è¢«ç½®ä¸º 1
```
示ä¾ï¼
```c
sockfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(addr)));
addr.sin_family = AF_INET;
addr.sin_port = htons(2000);
addr.sin_addr.s_addr = INADDR_ANY;
bind(sockfd, (struct sockaddr*)&addr, sizeof(addr));//ç»å®è¿æ¥
listen(sockfd, 5);//çå¬5个端å£
for(i = 0; i < 5; i++) {
memset(&client, e, sizeof(client));
addrlen = sizeof(client);
fds[i] = accept(sockfd, (struct sockaddr*)&client, &addrlen);
//å°çå¬ç对åºçæä»¶æè¿°ç¬¦fdåå
¥fdsï¼[3,4,5,6,7]
if(fds[i] > max)
max = fds[i];
}
while(1) {
FD_ZERO(&rset);//置为0
for(i = 0; i < 5; i++) {
FD_SET(fds[i], &rset);//对åºä½ç½®1 [0001 1111 00.....]
}
print("round again");
select(max + 1, &rset, NULL, NULL, NULL);//çå¬
for(i = 0; i <5; i++) {
if(FD_ISSET(fds[i], &rset)) {//夿çå¬åªä¸ä¸ªç«¯å£
memset(buffer, 0, MAXBUF);
read(fds[i], buffer, MAXBUF);//è¿å
¥å
æ ¸æè¯»æ°æ®
print(buffer);
}
}
}
```
åèè§é¢ï¼https://www.bilibili.com/video/BV19D4y1o797
****
##### æµç¨
select è°ç¨æµç¨å¾ï¼

1. ä½¿ç¨ copy_from_user ä»ç¨æ·ç©ºé´æ·è´ fd_set å°å
æ ¸ç©ºé´ï¼è¿ç¨é»å¡
2. 注ååè°å½æ° _pollwait
3. éåææ fdï¼è°ç¨å
¶å¯¹åºç poll æ¹æ³å¤æå½åè¯·æ±æ¯å¦åå¤å°±ç»ªï¼å¯¹äº socketï¼è¿ä¸ª poll æ¹æ³æ¯ sock_pollï¼sock_poll æ ¹æ®æ
åµä¼è°ç¨å° tcp_pollãudp_poll æè
datagram_pollï¼ä»¥ tcp_poll 为ä¾ï¼å
¶æ ¸å¿å®ç°å°±æ¯ _pollwait
4. _pollwait æ **currentï¼è°ç¨ select çè¿ç¨ï¼**æå°è®¾å¤ççå¾
éåï¼ä¸åè®¾å¤æä¸åççå¾
éåï¼å¯¹äº tcp_poll ï¼å
¶çå¾
é忝 sk â sk_sleepï¼æè¿ç¨æå°çå¾
éåä¸å¹¶ä¸ä»£è¡¨è¿ç¨å·²ç»ç¡ç ï¼ï¼å¨è®¾å¤æ¶å°æ¶æ¯ï¼ç½ç»è®¾å¤ï¼æå¡«åå®æä»¶æ°æ®ï¼ç£ç设å¤ï¼åï¼ä¼å¤é设å¤çå¾
éåä¸ç¡ç çè¿ç¨ï¼è¿æ¶ current 便被å¤éï¼è¿å
¥å°±ç»ªéå
5. poll æ¹æ³è¿åæ¶ä¼è¿åä¸ä¸ªæè¿°è¯»åæä½æ¯å¦å°±ç»ªç mask æ©ç ï¼æ ¹æ®è¿ä¸ª mask æ©ç ç» fd_set èµå¼
6. 妿éå宿æç fdï¼è¿æ²¡æè¿åä¸ä¸ªå¯è¯»åç mask æ©ç ï¼åä¼è°ç¨ schedule_timeout 让 current è¿ç¨è¿å
¥ç¡ç ãå½è®¾å¤é©±å¨åçèªèº«èµæºå¯è¯»ååï¼ä¼å¤éå
¶çå¾
éåä¸ç¡ç çè¿ç¨ï¼å¦æè¶
è¿ä¸å®çè¶
æ¶æ¶é´ï¼schedule_timeoutï¼æ²¡æå
¶ä»çº¿ç¨å¤éï¼åè°ç¨ select çè¿ç¨ä¼éæ°è¢«å¤éè·å¾ CPUï¼è¿èéæ°éå fdï¼å¤æææ²¡æå°±ç»ªç fd
7. æ fd_set ä»å
æ ¸ç©ºé´æ·è´å°ç¨æ·ç©ºé´ï¼é»å¡è¿ç¨ç»§ç»æ§è¡
åèæç« ï¼https://www.cnblogs.com/anker/p/3265058.html
å
¶ä»æµç¨å¾ï¼https://www.processon.com/view/link/5f62b9a6e401fd2ad7e5d6d1
****
#### poll
poll çåè½ä¸ select 类似ï¼ä¹æ¯çå¾
ä¸ç»æè¿°ç¬¦ä¸çä¸ä¸ªæä¸ºå°±ç»ªç¶æ
```c
int poll(struct pollfd *fds, unsigned int nfds, int timeout);
```
poll ä¸çæè¿°ç¬¦æ¯ pollfd ç±»åçæ°ç»ï¼pollfd çå®ä¹å¦ä¸ï¼
```c
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
```
select å poll 对æ¯ï¼
- select ä¼ä¿®æ¹æè¿°ç¬¦ï¼è poll ä¸ä¼
- select çæè¿°ç¬¦ç±»åä½¿ç¨æ°ç»å®ç°ï¼ææè¿°ç¬¦çéå¶ï¼è poll 使ç¨**é¾è¡¨**å®ç°ï¼æ²¡ææè¿°ç¬¦æ°éçéå¶
- poll æä¾äºæ´å¤çäºä»¶ç±»åï¼å¹¶ä¸å¯¹æè¿°ç¬¦çéå¤å©ç¨ä¸æ¯ select é«
* select å poll éåº¦é½æ¯è¾æ
¢ï¼**æ¯æ¬¡è°ç¨**é½éè¦å°å
¨é¨æè¿°ç¬¦æ°ç» fd ä»åºç¨è¿ç¨ç¼å²åºå¤å¶å°å
æ ¸ç¼å²åºï¼åæ¶æ¯æ¬¡é½éè¦å¨å
æ ¸éåä¼ éè¿æ¥çææ fd ï¼è¿ä¸ªå¼éå¨ fd å¾å¤æ¶ä¼å¾å¤§
* å 乿æçç³»ç»é½æ¯æ selectï¼ä½æ¯åªææ¯è¾æ°çç³»ç»æ¯æ poll
* select å poll çæ¶é´å¤æåº¦ O(n)ï¼å¯¹ socket è¿è¡æ«ææ¶æ¯çº¿æ§æ«æï¼å³éç¨è½®è¯¢çæ¹æ³ï¼æçè¾ä½ï¼å 为并ä¸ç¥éå
·ä½æ¯åªä¸ª socket å
·æäºä»¶ï¼æä»¥éç fd æ°éçå¢å ä¼é æéåé度æ
¢ç**线æ§ä¸é**æ§è½é®é¢
* poll è¿æä¸ä¸ªç¹ç¹æ¯æ°´å¹³è§¦åï¼å¦ææ¥åäº fd åï¼æ²¡æè¢«å¤çï¼é£ä¹ä¸æ¬¡ poll æ¶ä¼å次æ¥å该 fd
* 妿ä¸ä¸ªçº¿ç¨å¯¹æä¸ªæè¿°ç¬¦è°ç¨äº select æè
pollï¼å¦ä¸ä¸ªçº¿ç¨å
³éäºè¯¥æè¿°ç¬¦ï¼ä¼å¯¼è´è°ç¨ç»æä¸ç¡®å®
åèæç« ï¼https://github.com/CyC2018/CS-Notes/blob/master/notes/Socket.md
****
#### epoll
##### 彿°
epoll 使ç¨äºä»¶ç就绪éç¥æ¹å¼ï¼éè¿ epoll_ctl() åå
æ ¸æ³¨åæ°çæè¿°ç¬¦æè
æ¯æ¹åæä¸ªæä»¶æè¿°ç¬¦çç¶æã已注åçæè¿°ç¬¦å¨å
æ ¸ä¸ä¼è¢«ç»´æ¤å¨ä¸æ£µ**çº¢é»æ **ä¸ï¼ä¸æ¦è¯¥ fd 就绪ï¼**å
æ ¸éè¿ callback åè°å½æ°å° I/O åå¤å¥½çæè¿°ç¬¦å å
¥å°ä¸ä¸ªé¾è¡¨ä¸**管çï¼è¿ç¨è°ç¨ epoll_wait() 便å¯ä»¥å¾å°äºä»¶å°±ç»ªçæè¿°ç¬¦
```c
int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)ï¼
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
```
* epall_createï¼ä¸ä¸ªç³»ç»å½æ°ï¼å½æ°å°å¨å
æ ¸ç©ºé´å
å建ä¸ä¸ª epoll æ°æ®ç»æï¼å¯ä»¥ç解为 epoll ç»æç©ºé´ï¼è¿åå¼ä¸º epoll çæä»¶æè¿°ç¬¦ç¼å·ï¼ä»¥åæ client è¿æ¥æ¶ï¼å该 epoll ç»æä¸æ·»å çå¬ï¼æä»¥ epoll 使ç¨ä¸ä¸ªæä»¶æè¿°ç¬¦ç®¡çå¤ä¸ªæè¿°ç¬¦
* epall_ctlï¼epoll çäºä»¶æ³¨å彿°ï¼select 彿°æ¯è°ç¨æ¶æå®éè¦çå¬çæè¿°ç¬¦åäºä»¶ï¼epoll å
å°ç¨æ·æå
´è¶£çæè¿°ç¬¦äºä»¶æ³¨åå° epoll 空é´ãæ¤å½æ°æ¯éé»å¡å½æ°ï¼ç¨æ¥å¢å æ¹ epoll 空é´å
çæè¿°ç¬¦ï¼åæ°è§£éï¼
* epfdï¼epoll ç»æçè¿ç¨ fd ç¼å·ï¼å½æ°å°ä¾é 该ç¼å·æ¾å°å¯¹åºç epoll ç»æ
* opï¼è¡¨ç¤ºå½å请æ±ç±»åï¼æä¸ä¸ªå®å®ä¹ï¼
* EPOLL_CTL_ADDï¼æ³¨åæ°ç fd å° epfd ä¸
* EPOLL_CTL_MODï¼ä¿®æ¹å·²ç»æ³¨åç fd ççå¬äºä»¶
* EPOLL_CTI_DELï¼ä» epfd ä¸å é¤ä¸ä¸ª fd
* fdï¼éè¦çå¬çæä»¶æè¿°ç¬¦ï¼ä¸è¬æ socket_fd
* eventï¼åè¯å
æ ¸å¯¹è¯¥ fd èµæºæå
´è¶£çäºä»¶ï¼epoll_event çç»æï¼
```c
struct epoll_event {
_uint32_t events; /*epoll events*/
epoll_data_t data; /*user data variable*/
}
```
events å¯ä»¥æ¯ä»¥ä¸å 个å®éåï¼EPOLLINãEPOLOUTãEPOLLPRIãEPOLLERRãEPOLLHUPï¼ææï¼ãEPOLETï¼è¾¹ç¼è§¦åï¼ãEPOLLONESHOTï¼åªçå¬ä¸æ¬¡ï¼äºä»¶è§¦ååèªå¨æ¸
é¤è¯¥ fdï¼ä» epoll å表ï¼
* epoll_waitï¼çå¾
äºä»¶ç产çï¼ç±»ä¼¼äº select() è°ç¨ï¼è¿åå¼ä¸ºæ¬æ¬¡å°±ç»ªç fd 个æ°ï¼ç´æ¥ä»å°±ç»ªé¾è¡¨è·åï¼æ¶é´å¤æåº¦ O(1)
* epfdï¼**æå®æå
´è¶£ç epoll äºä»¶å表**
* eventsï¼æåä¸ä¸ª epoll_event ç»ææ°ç»ï¼å½å½æ°è¿åæ¶ï¼å
æ ¸ä¼æå°±ç»ªç¶æçæ°æ®æ·è´å°è¯¥æ°ç»
* maxeventsï¼æ æ epoll_event æ°ç»æå¤è½æ¥æ¶çæ°æ®éï¼å³æ¬æ¬¡æä½æå¤è½è·åå¤å°å°±ç»ªæ°æ®
* timeoutï¼åä½ä¸ºæ¯«ç§
* 0ï¼è¡¨ç¤ºç«å³è¿åï¼éé»å¡è°ç¨
* -1ï¼é»å¡è°ç¨ï¼ç´å°æç¨æ·æå
´è¶£çäºä»¶å°±ç»ªä¸ºæ¢
* å¤§äº 0ï¼é»å¡è°ç¨ï¼é»å¡æå®æ¶é´å
妿æäºä»¶å°±ç»ªåæåè¿åï¼å¦åçå¾
æå®æ¶é´åè¿å
epoll çæè¿°ç¬¦äºä»¶æä¸¤ç§è§¦å模å¼ï¼LTï¼level triggerï¼å ETï¼edge triggerï¼ï¼
* LT 模å¼ï¼å½ epoll_wait() æ£æµå°æè¿°ç¬¦äºä»¶å°è¾¾æ¶ï¼å°æ¤äºä»¶éç¥è¿ç¨ï¼è¿ç¨å¯ä»¥ä¸ç«å³å¤ç该äºä»¶ï¼ä¸æ¬¡è°ç¨ epoll_wait() ä¼å次éç¥è¿ç¨ï¼æ¯é»è®¤çä¸ç§æ¨¡å¼ï¼å¹¶ä¸åæ¶æ¯æ Blocking å No-Blocking
* ET 模å¼ï¼éç¥ä¹åè¿ç¨å¿
é¡»ç«å³å¤çäºä»¶ï¼ä¸æ¬¡åè°ç¨ epoll_wait() æ¶ä¸ä¼åå¾å°äºä»¶å°è¾¾çéç¥ãåå°äº epoll äºä»¶è¢«éå¤è§¦åçæ¬¡æ°ï¼å æ¤æçè¦æ¯ LT 模å¼é«ï¼åªæ¯æ No-Blockingï¼ä»¥é¿å
ç±äºä¸ä¸ª fd çé»å¡è¯»/é»å¡åæä½æå¤çå¤ä¸ªæä»¶æè¿°ç¬¦çä»»å¡é¥¥é¥¿
```c
// å建 epoll æè¿°ç¬¦ï¼æ¯ä¸ªåºç¨ç¨åºåªéè¦ä¸ä¸ªï¼ç¨äºçæ§ææå¥æ¥å
int pollingfd = epoll_create(0xCAFE);
if ( pollingfd < 0 )// report error
// åå§å epoll ç»æ
struct epoll_event ev = { 0 };
// å°è¿æ¥ç±»å®ä¾ä¸äºä»¶ç¸å
³èï¼å¯ä»¥å
³è任使³è¦çä¸è¥¿
ev.data.ptr = pConnection1;
// çè§è¾å
¥ï¼å¹¶ä¸å¨äºä»¶åçåä¸èªå¨éæ°åå¤æè¿°ç¬¦
ev.events = EPOLLIN | EPOLLONESHOT;
// å°æè¿°ç¬¦æ·»å å°çæ§å表ä¸ï¼å³ä½¿å¦ä¸ä¸ªçº¿ç¨å¨epoll_waitä¸çå¾
ï¼æè¿°ç¬¦å°è¢«æ£ç¡®æ·»å
if ( epoll_ctl( epollfd, EPOLL_CTL_ADD, pConnection1->getSocket(), &ev) != 0 )
// report error
// æå¤çå¾
20 个äºä»¶
struct epoll_event pevents[20];
// çå¾
10ç§ï¼æ£ç´¢20个并åå
¥epoll_eventæ°ç»
int ready = epoll_wait(pollingfd, pevents, 20, 10000);
// æ£æ¥epollæ¯å¦æå
if ( ret == -1)// report error and abort
else if ( ret == 0)// timeout; no event detected
else
{
for (int i = 0; i < ready; i+ )
{
if ( pevents[i].events & EPOLLIN )
{
// è·åè¿æ¥æé
Connection * c = (Connection*) pevents[i].data.ptr;
c->handleReadEvent();
}
}
}
```
æµç¨å¾ï¼https://gitee.com/seazean/images/blob/master/Java/IO-epoll%E5%8E%9F%E7%90%86%E5%9B%BE.jpg
åèè§é¢ï¼https://www.bilibili.com/video/BV19D4y1o797
***
##### ç¹ç¹
epoll çç¹ç¹ï¼
* epoll ä»
éç¨äº Linux ç³»ç»
* epoll 使ç¨**ä¸ä¸ªæä»¶æè¿°ç¬¦ç®¡çå¤ä¸ªæè¿°ç¬¦**ï¼å°ç¨æ·å
³å¿çæä»¶æè¿°ç¬¦çäºä»¶åæ¾å°å
æ ¸çä¸ä¸ªäºä»¶è¡¨ï¼ä¸ªäººçè§£æåå
èç¹ï¼
* 没ææå¤§æè¿°ç¬¦æ°éï¼å¹¶åè¿æ¥ï¼çéå¶ï¼æå¼ fd çä¸éè¿å¤§äº1024ï¼1G å
åè½çå¬çº¦ 10 ä¸ä¸ªç«¯å£ï¼
* epoll çæ¶é´å¤æåº¦ O(1)ï¼epoll ç解为 event pollï¼ä¸åäºå¿è½®è¯¢åæ å·®å«è½®è¯¢ï¼è°ç¨ epoll_wait **åªæ¯è½®è¯¢å°±ç»ªé¾è¡¨**ãå½çå¬å表æè®¾å¤å°±ç»ªæ¶è°ç¨åè°å½æ°ï¼æå°±ç»ª fd æ¾å
¥å°±ç»ªé¾è¡¨ä¸ï¼å¹¶å¤éå¨ epoll_wait ä¸é»å¡çè¿ç¨ï¼æä»¥ epoll å®é
䏿¯**äºä»¶é©±å¨**ï¼æ¯ä¸ªäºä»¶å
³èä¸fdï¼çï¼éä½äº system call çæ¶é´å¤æåº¦
* epoll å
æ ¸ä¸æ ¹æ®æ¯ä¸ª fd ä¸ç callback 彿°æ¥å®ç°ï¼åªææ´»è·ç socket æä¼ä¸»å¨è°ç¨ callbackï¼æä»¥ä½¿ç¨ epoll 没æåé¢ä¸¤è
ç线æ§ä¸éçæ§è½é®é¢ï¼æçæé«
* epoll æ³¨åæ°çäºä»¶æ¯æ³¨åå°å°å
æ ¸ä¸ epoll 奿ä¸ï¼ä¸éè¦æ¯æ¬¡è°ç¨ epoll_wait æ¶é夿·è´ï¼å¯¹æ¯åé¢ä¸¤ç§åªéè¦å°æè¿°ç¬¦ä»è¿ç¨ç¼å²åºåå
æ ¸ç¼å²åº**æ·è´ä¸æ¬¡**ï¼ä¹å¯ä»¥å©ç¨ **mmap() æä»¶æ å°å
å**å éä¸å
æ ¸ç©ºé´çæ¶æ¯ä¼ éï¼åªæ¯å¯ä»¥ç¨ï¼å¹¶æ²¡æç¨ï¼
* åé¢ä¸¤è
è¦æ current å¾è®¾å¤çå¾
éå䏿䏿¬¡ï¼epoll ä¹åªæ current å¾çå¾
éå䏿䏿¬¡ï¼ä½æ¯è¿éççå¾
éå并䏿¯è®¾å¤çå¾
éåï¼åªæ¯ä¸ä¸ª epoll å
é¨å®ä¹ççå¾
éåï¼è¿æ ·å¯ä»¥èçå¼é
* epoll 对å¤çº¿ç¨ç¼ç¨æ´æå好ï¼ä¸ä¸ªçº¿ç¨è°ç¨äº epoll_wait() å¦ä¸ä¸ªçº¿ç¨å
³éäºåä¸ä¸ªæè¿°ç¬¦ï¼ä¹ä¸ä¼äº§çå select å poll çä¸ç¡®å®æ
åµ
åèæç« ï¼https://www.jianshu.com/p/dfd940e7fca2
åèæç« ï¼https://www.cnblogs.com/anker/p/3265058.html
***
#### åºç¨
åºç¨åºæ¯ï¼
* select åºç¨åºæ¯ï¼
* select ç timeout åæ°ç²¾åº¦ä¸ºå¾®ç§ï¼poll å epoll 为毫ç§ï¼å æ¤ select éç¨**宿¶æ§è¦æ±æ¯è¾é«**çåºæ¯ï¼æ¯å¦æ ¸ååºå çæ§å¶
* select å¯ç§»æ¤æ§æ´å¥½ï¼å ä¹è¢«ææä¸»æµå¹³å°ææ¯æ
* poll åºç¨åºæ¯ï¼poll 没ææå¤§æè¿°ç¬¦æ°éçéå¶ï¼éç¨äºå¹³å°æ¯æå¹¶ä¸å¯¹å®æ¶æ§è¦æ±ä¸é«çæ
åµ
* epoll åºç¨åºæ¯ï¼
* è¿è¡å¨ Linux å¹³å°ä¸ï¼æå¤§éçæè¿°ç¬¦éè¦åæ¶è½®è¯¢ï¼å¹¶ä¸è¿äºè¿æ¥æå¥½æ¯**é¿è¿æ¥**
* éè¦åæ¶çæ§å°äº 1000 个æè¿°ç¬¦ï¼æ²¡å¿
è¦ä½¿ç¨ epollï¼å 为è¿ä¸ªåºç¨åºæ¯ä¸å¹¶ä¸è½ä½ç° epoll çä¼å¿
* éè¦çæ§çæè¿°ç¬¦ç¶æååå¤ï¼è䏿¯é常çæçï¼å°±æ²¡æå¿
è¦ä½¿ç¨ epollãå 为 epoll ä¸çæææè¿°ç¬¦é½åå¨å¨å
æ ¸ä¸ï¼æ¯æ¬¡å¯¹æè¿°ç¬¦çç¶ææ¹åé½éè¦éè¿ epoll_ctl() è¿è¡ç³»ç»è°ç¨ï¼é¢ç¹ç³»ç»è°ç¨é使çï¼å¹¶ä¸ epoll çæè¿°ç¬¦åå¨å¨å
æ ¸ï¼ä¸å®¹æè°è¯
åèæç« ï¼https://github.com/CyC2018/CS-Notes/blob/master/notes/Socket.md
****
### ç³»ç»è°ç¨
#### å
æ ¸æ
ç¨æ·ç©ºé´ï¼ç¨æ·ä»£ç ãç¨æ·å æ
å
æ ¸ç©ºé´ï¼å
æ ¸ä»£ç ãå
æ ¸è°åº¦ç¨åºãè¿ç¨æè¿°ç¬¦ï¼å
æ ¸å æ ãthread_info è¿ç¨æè¿°ç¬¦ï¼
* è¿ç¨æè¿°ç¬¦åç¨æ·çè¿ç¨æ¯ä¸ä¸å¯¹åºç
* SYS_API ç³»ç»è°ç¨ï¼å¦ readãwriteï¼ç³»ç»è°ç¨å°±æ¯ 0X80 䏿
* è¿ç¨æè¿°ç¬¦ pdï¼è¿ç¨ä»ç¨æ·æåæ¢å°å
æ ¸ææ¶ï¼éè¦**ä¿åç¨æ·ææ¶çä¸ä¸æä¿¡æ¯å¨ PCB ä¸**
* 线ç¨ä¸ä¸æï¼ç¨æ·ç¨åºåºå°åï¼ç¨åºè®¡æ°å¨ãcpu cacheãå¯åå¨çï¼æ¹ä¾¿ç¨åºååç¨æ·ææ¶æ¢å¤ç°åº
* å
æ ¸å æ ï¼**ç³»ç»è°ç¨å½æ°ä¹æ¯è¦å建åéçï¼**è¿äºåéå¨å
æ ¸å æ ä¸åé

***
#### 80䏿
å¨ç¨æ·ç¨åºä¸è°ç¨æä½ç³»ç»æä¾çæ ¸å¿æçº§å«çååè½ï¼ä¸ºäºç³»ç»å®å
¨éè¦è¿è¡ç¨æ·æåå
æ ¸æè½¬æ¢ï¼ç¶æç转æ¢éè¦è¿è¡ CPU 䏿ï¼ä¸æåä¸ºç¡¬ä¸æåè½¯ä¸æï¼
* ç¡¬ä¸æï¼å¦ç½ç»ä¼ è¾ä¸ï¼æ°æ®å°è¾¾ç½å¡åï¼ç½å¡ç»è¿ä¸ç³»åæä½ååèµ·ç¡¬ä»¶ä¸æ
* è½¯ä¸æï¼å¦ç¨åºè¿è¡è¿ç¨ä¸æ¬èº«äº§ççä¸äºä¸æ
- åèµ· `0X80` 䏿
- ç¨åºæ§è¡ç¢°å°é¤ 0 å¼å¸¸
ç³»ç»è°ç¨ system_call 彿°æå¯¹åºç䏿æä»¤ç¼å·æ¯ 0X80ï¼åè¿å¶æ¯ 8Ã16=128ï¼ï¼è该æä»¤ç¼å·å¯¹åºçå°±æ¯ç³»ç»è°ç¨ç¨åºçå
¥å£ï¼æä»¥ç§°ç³»ç»è°ç¨ä¸º 80 䏿
ç³»ç»è°ç¨çæµç¨ï¼
* å¨ CPU å¯åå¨éåä¸ä¸ªç³»ç»è°ç¨å·ï¼è¡¨ç¤ºåªä¸ªç³»ç»å½æ°ï¼æ¯å¦ read
* å° CPU çä¸´æ¶æ°æ®é½ä¿åå° thread_info ä¸
* æ§è¡ 80 䏿å¤çç¨åºï¼æ¾å°åååçç³»ç»è°ç¨å·ï¼readï¼ï¼å
æ£æ¥ç¼åä¸ææ²¡æå¯¹åºçæ°æ®ï¼æ²¡æå°±å»ç£çä¸å è½½å°å
æ ¸ç¼å²åºï¼ç¶åä»å
æ ¸ç¼å²åºæ·è´å°ç¨æ·ç©ºé´
* æåæ¢å¤å°ç¨æ·æï¼éè¿ thread_info æ¢å¤ç°åºï¼ç¨æ·æç»§ç»æ§è¡

åèè§é¢ï¼https://www.bilibili.com/video/BV19D4y1o797
****
### é¶æ·è´
#### DMA
DMA (Direct Memory Access) ï¼ç´æ¥åå¨å¨è®¿é®ï¼è®©å¤é¨è®¾å¤ä¸éè¿ CPU ç´æ¥ä¸ç³»ç»å
åäº¤æ¢æ°æ®çæ¥å£ææ¯
ä½ç¨ï¼å¯ä»¥è§£å³æ¹éæ°æ®çè¾å
¥/è¾åºé®é¢ï¼ä½¿æ°æ®çä¼ éé度åå³äºåå¨å¨åå¤è®¾çå·¥ä½é度
æå
åæ°æ®ä¼ è¾å°ç½å¡ç¶ååéï¼
* 没æ DMAï¼CPU 读å
åæ°æ®å° CPU é«éç¼åï¼ååå°ç½å¡ï¼è¿æ ·å°±æ CPU çé度æä½å°åç½å¡ä¸ä¸ªé度
* ä½¿ç¨ DMAï¼ææ°æ®è¯»å° Socket å
æ ¸ç¼ååºï¼CPU å¤å¶ï¼ï¼CPU åé
ç» DMA å¼å§**弿¥**æä½ï¼DMA 读å Socket ç¼å²åºå° DMA ç¼å²åºï¼ç¶ååå°ç½å¡ãDMA æ§è¡å®å**䏿**ï¼å°±æ¯éç¥ï¼ CPUï¼è¿æ¶ Socket å
æ ¸ç¼å²åºä¸ºç©ºï¼CPU ä»ç¨æ·æåæ¢å°å
æ ¸æï¼æ§è¡ä¸æå¤çç¨åºï¼å°éè¦ä½¿ç¨ Socket ç¼å²åºçé»å¡è¿ç¨ç§»å°å°±ç»ªéå
ä¸ä¸ªå®æ´ç DMA ä¼ è¾è¿ç¨å¿
é¡»ç»å DMA 请æ±ãDMA ååºãDMA ä¼ è¾ãDMA ç»æå个æ¥éª¤ï¼
DMA æ¹å¼æ¯ä¸ç§å®å
¨ç±ç¡¬ä»¶è¿è¡ä¿¡æ¯ä¼ éçæ§å¶æ¹å¼ï¼éå¸¸ç³»ç»æ»çº¿ç± CPU 管çï¼å¨ DMA æ¹å¼ä¸ï¼CPU ç䏻忧å¶ä¿¡å·è¢«ç¦æ¢ä½¿ç¨ï¼CPU ææ»çº¿ï¼å°åæ»çº¿ãæ°æ®æ»çº¿ãæ§å¶æ»çº¿ï¼è®©åºæ¥ç± DMA æ§å¶å¨æ¥ç®¡ï¼ç¨æ¥æ§å¶ä¼ éçåèæ°ã夿 DMA æ¯å¦ç»æã以åååº DMA ç»æä¿¡å·ï¼æä»¥ DMA æ§å¶å¨å¿
é¡»æä»¥ä¸åè½ï¼
* æ¥åå¤è®¾ååºç DMA 请æ±ï¼å¹¶å CPU ååºæ»çº¿æ¥ç®¡è¯·æ±
* å½ CPU ååºå
许æ¥ç®¡ä¿¡å·åï¼è¿å
¥ DMA æä½å¨æ
* ç¡®å®ä¼ éæ°æ®ç主ååå
å°ååé¿åº¦ï¼å¹¶èªå¨ä¿®æ¹ä¸»åå°å计æ°åä¼ éé¿åº¦è®¡æ°
* è§å®æ°æ®å¨ä¸»ååå¤è®¾é´çä¼ éæ¹åï¼ååºè¯»åçæ§å¶ä¿¡å·ï¼æ§è¡æ°æ®ä¼ éæä½
* 夿 DMA ä¼ éæ¯å¦ç»æï¼ååº DMA ç»æä¿¡å·ï¼ä½¿ CPU æ¢å¤æ£å¸¸å·¥ä½ç¶æï¼ä¸æï¼
***
#### BIO
ä¼ ç»ç I/O æä½è¿è¡äº 4 æ¬¡ç¨æ·ç©ºé´ä¸å
æ ¸ç©ºé´çä¸ä¸æåæ¢ï¼ä»¥å 4 æ¬¡æ°æ®æ·è´ï¼
* JVM ååº read ç³»ç»è°ç¨ï¼OS ä¸ä¸æåæ¢å°å
æ ¸æ¨¡å¼ï¼åæ¢ 1ï¼å¹¶å°æ°æ®ä»ç½å¡æç¡¬çç设å¤éè¿ DMA 读åå°å
æ ¸ç©ºé´ç¼å²åºï¼æ·è´ 1ï¼ï¼å
æ ¸ç¼å²åºå®é
䏿¯**ç£çé«éç¼åï¼PageCacheï¼**
* OS å
æ ¸å°æ°æ®å¤å¶å°ç¨æ·ç©ºé´ç¼å²åºï¼æ·è´ 2ï¼ï¼ç¶å read ç³»ç»è°ç¨è¿åï¼åä¼å¯¼è´ä¸æ¬¡å
æ ¸ç©ºé´å°ç¨æ·ç©ºé´çä¸ä¸æåæ¢ï¼åæ¢ 2ï¼
* JVM å¤ç代ç é»è¾å¹¶åé write() ç³»ç»è°ç¨ï¼OS ä¸ä¸æåæ¢å°å
æ ¸æ¨¡å¼ï¼åæ¢3ï¼å¹¶ä»ç¨æ·ç©ºé´ç¼å²åºå¤å¶æ°æ®å°å
æ ¸ç©ºé´ç¼å²åºï¼æ·è´3ï¼
* å°å
æ ¸ç©ºé´ç¼å²åºä¸çæ°æ®åå° hardwareï¼æ·è´4ï¼ï¼write ç³»ç»è°ç¨è¿åï¼å¯¼è´å
æ ¸ç©ºé´å°ç¨æ·ç©ºé´ç忬¡ä¸ä¸æåæ¢ï¼åæ¢4ï¼
æµç¨å¾ä¸çç®å¤´åè¿æ¥ä¹æç«ï¼å¯ä»¥ä»ç½å¡è·åæ°æ®

read è°ç¨å¾ç¤ºï¼readãwrite 齿¯ç³»ç»è°ç¨æä»¤
***
#### mmap
mmapï¼Memory Mapped Filesï¼å
åæ å°å write å®ç°é¶æ·è´ï¼**é¶æ·è´å°±æ¯æ²¡ææ°æ®ä»å
æ ¸ç©ºé´å¤å¶å°ç¨æ·ç©ºé´**
ç¨æ·ç©ºé´åå
æ ¸ç©ºé´é½ä½¿ç¨å
åï¼æä»¥å¯ä»¥å
±äº«åä¸åç©çå
åå°åï¼çå»ç¨æ·æåå
æ ¸æä¹é´çæ·è´ãåç½å¡æ¶ï¼å
±äº«ç©ºé´çå
容æ·è´å° Socket ç¼å²åºï¼ç¶åäº¤ç» DMA åéå°ç½å¡ï¼åªéè¦ 3 次å¤å¶
è¿è¡äº 4 æ¬¡ç¨æ·ç©ºé´ä¸å
æ ¸ç©ºé´çä¸ä¸æåæ¢ï¼ä»¥å 3 æ¬¡æ°æ®æ·è´ï¼2 次 DMAï¼ä¸æ¬¡ CPU å¤å¶ï¼ï¼
* ååº mmap ç³»ç»è°ç¨ï¼DMA æ·è´å°å
æ ¸ç¼å²åºï¼æ å°å°å
±äº«ç¼å²åºï¼mmap ç³»ç»è°ç¨è¿åï¼æ éæ·è´
* ååº write ç³»ç»è°ç¨ï¼å°æ°æ®ä»å
æ ¸ç¼å²åºæ·è´å°å
æ ¸ Socket ç¼å²åºï¼write ç³»ç»è°ç¨è¿åï¼DMA å°å
æ ¸ç©ºé´ Socket ç¼å²åºä¸çæ°æ®ä¼ éå°åè®®å¼æ

åçï¼å©ç¨æä½ç³»ç»ç Page æ¥å®ç°æä»¶å°ç©çå
åçç´æ¥æ å°ï¼å®ææ å°å对ç©çå
åçæä½ä¼**è¢«åæ¥**å°ç¡¬çä¸
缺ç¹ï¼ä¸å¯é ï¼åå° mmap ä¸çæ°æ®å¹¶æ²¡æè¢«çæ£çåå°ç¡¬çï¼æä½ç³»ç»ä¼å¨ç¨åºä¸»å¨è°ç¨ flush çæ¶åæææ°æ®çæ£çåå°ç¡¬ç
Java NIO æä¾äº **MappedByteBuffer** ç±»å¯ä»¥ç¨æ¥å®ç° mmap å
åæ å°ï¼MappedByteBuffer 类对象**åªè½éè¿è°ç¨ `FileChannel.map()` è·å**
****
#### sendfile
sendfile å®ç°é¶æ·è´ï¼æå¼æä»¶çæä»¶æè¿°ç¬¦ fd å socket ç fd ä¼ éç» sendfileï¼ç¶åç»è¿ 3 次å¤å¶å 2 æ¬¡ç¨æ·æåå
æ ¸æç忢
åçï¼æ°æ®æ ¹æ¬ä¸ç»è¿ç¨æ·æï¼ç´æ¥ä»å
æ ¸ç¼å²åºè¿å
¥å° Socket Bufferï¼ç±äºåç¨æ·æå®å
¨æ å
³ï¼å°±åå°äºä¸¤æ¬¡ä¸ä¸æåæ¢
说æï¼é¶æ·è´ææ¯æ¯ä¸å
许è¿ç¨å¯¹æä»¶å
容ä½è¿ä¸æ¥çå å·¥çï¼æ¯å¦åç¼©æ°æ®ååé

sendfile2.4 ä¹åï¼sendfile å®ç°äºæ´ç®åçæ¹å¼ï¼æä»¶å°è¾¾å
æ ¸ç¼å²åºåï¼ä¸å¿
åå°æ°æ®å
¨é¨å¤å¶å° socket buffer ç¼å²åºï¼èæ¯åª**å°è®°å½æ°æ®ä½ç½®åé¿åº¦ç¸å
³çæè¿°ç¬¦ä¿¡æ¯**ä¿åå° socket bufferï¼DMA æ ¹æ® Socket ç¼å²åºä¸æè¿°ç¬¦æä¾çä½ç½®ååç§»éä¿¡æ¯ç´æ¥å°å
æ ¸ç©ºé´ç¼å²åºä¸çæ°æ®æ·è´å°åè®®å¼æä¸ï¼2 次å¤å¶ 2 æ¬¡åæ¢ï¼
Java NIO 对 sendfile çæ¯ææ¯ `FileChannel.transferTo()/transferFrom()`ï¼æç£çæä»¶è¯»å OS å
æ ¸ç¼å²åºåç fileChannelï¼ç´æ¥è½¬ç» socketChannel åéï¼åºå±å°±æ¯ sendfile
åèæç« ï¼https://blog.csdn.net/hancoder/article/details/112149121
***
## BIO
### Inet
ä¸ä¸ª InetAddress ç±»ç对象就代表ä¸ä¸ª IP å°å对象
æåæ¹æ³ï¼
* `static InetAddress getLocalHost()`ï¼è·å¾æ¬å°ä¸»æº IP å°å对象
* `static InetAddress getByName(String host)`ï¼æ ¹æ® IP å°åå符串æä¸»æºåè·å¾å¯¹åºç IP å°å对象
* `String getHostName()`ï¼è·å主æºå
* `String getHostAddress()`ï¼è·å¾ IP å°åå符串
```java
public class InetAddressDemo {
public static void main(String[] args) throws Exception {
// 1.è·åæ¬æºå°å对象
InetAddress ip = InetAddress.getLocalHost();
System.out.println(ip.getHostName());//DESKTOP-NNMBHQR
System.out.println(ip.getHostAddress());//192.168.11.1
// 2.è·åååip对象
InetAddress ip2 = InetAddress.getByName("www.baidu.com");
System.out.println(ip2.getHostName());//www.baidu.com
System.out.println(ip2.getHostAddress());//14.215.177.38
// 3.è·åå
¬ç½IP对象ã
InetAddress ip3 = InetAddress.getByName("182.61.200.6");
System.out.println(ip3.getHostName());//182.61.200.6
System.out.println(ip3.getHostAddress());//182.61.200.6
// 4.夿æ¯å¦è½éï¼ ping 5sä¹åæµè¯æ¯å¦å¯é
System.out.println(ip2.isReachable(5000)); // pingç¾åº¦
}
}
```
***
### UDP
#### åºæ¬ä»ç»
UDPï¼User Datagram Protocolï¼åè®®çç¹ç¹ï¼
* é¢åæ è¿æ¥çåè®®ï¼åé端åªç®¡åéï¼ä¸ç¡®è®¤å¯¹æ¹æ¯å¦è½æ¶å°ï¼é度快ï¼ä½æ¯ä¸å¯é ï¼ä¼ä¸¢å¤±æ°æ®
* å°½æå¤§åªå交ä»ï¼æ²¡ææ¥å¡æ§å¶
* åºäºæ°æ®å
è¿è¡æ°æ®ä¼ è¾ï¼åéæ°æ®çå
ç大å°éå¶ **64KB** 以å
* æ¯æä¸å¯¹ä¸ãä¸å¯¹å¤ãå¤å¯¹ä¸ãå¤å¯¹å¤ç交äºéä¿¡
UDP åè®®ç使ç¨åºæ¯ï¼å¨çº¿è§é¢ãç½ç»è¯é³ãçµè¯
***
#### å®ç°UDP
UDP åè®®ç¸å
³ç两个类ï¼
* DatagramPacketï¼æ°æ®å
对象ï¼ï¼ç¨æ¥å°è£
è¦åéæè¦æ¥æ¶çæ°æ®ï¼æ¯å¦ï¼éè£
ç®±
* DatagramSocketï¼åé对象ï¼ï¼ç¨æ¥åéææ¥æ¶æ°æ®å
ï¼æ¯å¦ï¼ç 头
**DatagramPacket**ï¼
* DatagramPacket ç±»ï¼
`public new DatagramPacket(byte[] buf, int length, InetAddress address, int port)`ï¼å建åéç«¯æ°æ®å
对象
* bufï¼è¦åéçå
容ï¼åèæ°ç»
* lengthï¼è¦åéå
容çé¿åº¦ï¼å使¯åè
* addressï¼æ¥æ¶ç«¯çIPå°å对象
* portï¼æ¥æ¶ç«¯ç端å£å·
`public new DatagramPacket(byte[] buf, int length)`ï¼åå»ºæ¥æ¶ç«¯çæ°æ®å
对象
* bufï¼ç¨æ¥å卿¥æ¶å°å
容
* lengthï¼è½å¤æ¥æ¶å
容çé¿åº¦
* DatagramPacket ç±»å¸¸ç¨æ¹æ³ï¼
* `public int getLength()`ï¼è·å¾å®é
æ¥æ¶å°çåè个æ°
* `public byte[] getData()`ï¼è¿åæ°æ®ç¼å²åº
**DatagramSocket**ï¼
* DatagramSocket ç±»æé æ¹æ³ï¼
* `protected DatagramSocket()`ï¼å建åé端ç Socket 对象ï¼ç³»ç»ä¼éæºåé
ä¸ä¸ªç«¯å£å·
* `protected DatagramSocket(int port)`ï¼åå»ºæ¥æ¶ç«¯ç Socket 对象并æå®ç«¯å£å·
* DatagramSocket ç±»æåæ¹æ³ï¼
* `public void send(DatagramPacket dp)`ï¼åéæ°æ®å
* `public void receive(DatagramPacket p)`ï¼æ¥æ¶æ°æ®å
* `public void close()`ï¼å
³éæ°æ®æ¥å¥æ¥å
```java
public class UDPClientDemo {
public static void main(String[] args) throws Exception {
System.out.println("===å¯å¨å®¢æ·ç«¯===");
// 1.å建ä¸ä¸ªéè£
箱对象ï¼ç¨äºå°è£
éè¦åéçæ°æ®å
!
byte[] buffer = "æå¦Java".getBytes();
DatagramPacket packet = new DatagramPacket(buffer,bubffer.length,InetAddress.getLoclHost,8000);
// 2.å建ä¸ä¸ªç 头对象
DatagramSocket socket = new DatagramSocket();
// 3.å¼å§åéæ°æ®å
对象
socket.send(packet);
socket.close();
}
}
public class UDPServerDemo{
public static void main(String[] args) throws Exception {
System.out.println("==å¯å¨æå¡ç«¯ç¨åº==");
// 1.å建ä¸ä¸ªæ¥æ¶å®¢æ·é½ç«¯çæ°æ®å
对象ï¼éè£
ç®±ï¼
byte[] buffer = new byte[1024*64];
DatagramPacket packet = new DatagramPacket(buffer, bubffer.length);
// 2.å建ä¸ä¸ªæ¥æ¶ç«¯çç 头对象
DatagramSocket socket = new DatagramSocket(8000);
// 3.å¼å§æ¥æ¶
socket.receive(packet);
// 4.ä»éè£
ç®±ä¸è·åæ¬æ¬¡è¯»åçæ°æ®é
int len = packet.getLength();
// 5.è¾åºæ°æ®
// String rs = new String(socket.getData(), 0, len)
String rs = new String(buffer , 0 , len);
System.out.println(rs);
// 6.æå¡ç«¯è¿å¯ä»¥è·ååæ¥ä¿¡æ¯ç客æ·ç«¯çIPå端å£ã
String ip = packet.getAddress().getHostAdress();
int port = packet.getPort();
socket.close();
}
}
```
***
#### é讯æ¹å¼
UDP éä¿¡æ¹å¼ï¼
+ åæï¼ç¨äºä¸¤ä¸ªä¸»æºä¹é´ç端对端éä¿¡
+ ç»æï¼ç¨äºå¯¹ä¸ç»ç¹å®ç主æºè¿è¡éä¿¡
IP : 224.0.1.0
Socket 对象 : MulticastSocket
+ 广æï¼ç¨äºä¸ä¸ªä¸»æºå¯¹æ´ä¸ªå±åç½ä¸ææä¸»æºä¸çæ°æ®éä¿¡
IP : 255.255.255.255
Socket 对象 : DatagramSocket
***
### TCP
#### åºæ¬ä»ç»
TCP/IP (Transfer Control Protocol) åè®®ï¼ä¼ è¾æ§å¶åè®®
TCP/IP åè®®çç¹ç¹ï¼
* é¢åè¿æ¥çåè®®ï¼æä¾å¯é 交äºï¼é度æ
¢
* ç¹å¯¹ç¹çå
¨åå·¥éä¿¡
* éè¿**䏿¬¡æ¡æ**建ç«è¿æ¥ï¼è¿æ¥æåå½¢ææ°æ®ä¼ è¾ééï¼éè¿**忬¡æ¥æ**æå¼è¿æ¥
* åºäºåèæµè¿è¡æ°æ®ä¼ è¾ï¼ä¼ è¾æ°æ®å¤§å°æ²¡æéå¶
TCP åè®®ç使ç¨åºæ¯ï¼æä»¶ä¸ä¼ åä¸è½½ãé®ä»¶åé忥æ¶ãè¿ç¨ç»å½
注æï¼**TCP ä¸ä¼ä¸ºæ²¡ææ°æ®ç ACK è¶
æ¶éä¼ **
æ¨èé
读ï¼https://yuanrengu.com/2020/77eef79f.html
***
#### Socket
TCP éä¿¡ä¹å« **Socket ç½ç»ç¼ç¨**ï¼åªè¦ä»£ç åºäº Socket å¼åï¼åºå±å°±æ¯åºäºäºå¯é ä¼ è¾ç TCP éä¿¡
ååéä¿¡ï¼Java Socket æ¯å
¨åå·¥çï¼å¨ä»»ææ¶å»ï¼çº¿è·¯ä¸åå¨ `A -> B` å `B -> A` çååä¿¡å·ä¼ è¾ï¼å³ä½¿æ¯é»å¡ IOï¼è¯»åå乿¯å¯ä»¥åæ¶è¿è¡çï¼åªè¦åå«éç¨è¯»çº¿ç¨åå线ç¨å³å¯ï¼è¯»ä¸ä¼é»å¡åãåä¹ä¸ä¼é»å¡è¯»
TCP åè®®ç¸å
³çç±»ï¼
* Socketï¼ä¸ä¸ªè¯¥ç±»ç对象就代表ä¸ä¸ªå®¢æ·ç«¯ç¨åºã
* ServerSocketï¼ä¸ä¸ªè¯¥ç±»ç对象就代表ä¸ä¸ªæå¡å¨ç«¯ç¨åºã
Socket ç±»ï¼
* æé æ¹æ³ï¼
* `Socket(InetAddress address,int port)`ï¼å建æµå¥æ¥åå¹¶å°å
¶è¿æ¥å°æå® IP æå®ç«¯å£å·
* `Socket(String host, int port)`ï¼æ ¹æ® IP å°åå符串å端å£å·å建客æ·ç«¯ Socket 对象
注æäºé¡¹ï¼**æ§è¡è¯¥æ¹æ³ï¼å°±ä¼ç«å³è¿æ¥æå®çæå¡å¨ï¼è¿æ¥æåï¼åè¡¨ç¤ºä¸æ¬¡æ¡æéè¿**ï¼å乿åºå¼å¸¸
* å¸¸ç¨ APIï¼
* `OutputStream getOutputStream()`ï¼è·å¾åèè¾åºæµå¯¹è±¡
* `InputStream getInputStream()`ï¼è·å¾åèè¾å
¥æµå¯¹è±¡
* `void shutdownInput()`ï¼åæ¢æ¥å
* `void shutdownOutput()`ï¼åæ¢åéæ°æ®ï¼ç»æ¢éä¿¡
* `SocketAddress getRemoteSocketAddress() `ï¼è¿å奿¥åè¿æ¥å°ç端ç¹çå°åï¼æªè¿æ¥è¿å null
ServerSocket ç±»ï¼
* æé æ¹æ³ï¼`public ServerSocket(int port)`
* å¸¸ç¨ APIï¼`public Socket accept()`ï¼**é»å¡çå¾
**æ¥æ¶ä¸ä¸ªå®¢æ·ç«¯ç Socket 管éè¿æ¥è¯·æ±ï¼è¿æ¥æåè¿åä¸ä¸ª Socket 对象
䏿¬¡æ¡æå TCP è¿æ¥å»ºç«æåï¼æå¡å¨å
æ ¸ä¼æè¿æ¥ä» SYN åè¿æ¥éåï¼ä¸æ¬¡æ¡ææ¶å¨æå¡ç«¯å»ºç«çéåï¼ä¸ç§»åºï¼ç§»å
¥ accept å
¨è¿æ¥éåï¼çå¾
è¿ç¨è°ç¨ accept 彿°æ¶æè¿æ¥ååºã妿è¿ç¨ä¸è½åæ¶è°ç¨ accept 彿°ï¼å°±ä¼é æ accept éåæº¢åºï¼æç»å¯¼è´å»ºç«å¥½ç TCP è¿æ¥è¢«ä¸¢å¼
**ç¸å½äº**客æ·ç«¯åæå¡å¨å»ºç«ä¸ä¸ªæ°æ®ç®¡éï¼èè¿æ¥ï¼ä¸æ¯çæ£çç©çè¿æ¥ï¼ï¼ç®¡éä¸è¬ä¸ç¨ close
***
#### å®ç°TCP
##### å¼åæµç¨
客æ·ç«¯çå¼åæµç¨ï¼
1. 客æ·ç«¯è¦è¯·æ±äºæå¡ç«¯ç Socket 管éè¿æ¥
2. ä» Socket é信管éä¸å¾å°ä¸ä¸ªåèè¾åºæµ
3. éè¿åèè¾åºæµç»æå¡ç«¯ååºæ°æ®
æå¡ç«¯çå¼åæµç¨ï¼
1. ç¨ ServerSocket 注å端å£
2. æ¥æ¶å®¢æ·ç«¯ç Socket 管éè¿æ¥
3. ä» Socket é信管éä¸å¾å°ä¸ä¸ªåèè¾å
¥æµ
4. ä»åèè¾å
¥æµä¸è¯»å客æ·ç«¯åæ¥çæ°æ®


* 妿è¾åºç¼å²åºç©ºé´ä¸å¤åæ¾ä¸»æºåéçæ°æ®ï¼åä¼è¢«é»å¡ï¼è¾å
¥ç¼å²åºåç
* ç¼å²åºä¸å±äºåºç¨ç¨åºï¼å±äºå
æ ¸
* TCP ä»è¾åºç¼å²åºè¯»åæ°æ®ä¼å éé»å¡çº¿ç¨
***
##### å®ç°éä¿¡
éæ±ä¸ï¼å®¢æ·ç«¯åéä¸è¡æ°æ®ï¼æå¡ç«¯æ¥æ¶ä¸è¡æ°æ®
````java
public class ClientDemo {
public static void main(String[] args) throws Exception {
// 1.客æ·ç«¯è¦è¯·æ±äºæå¡ç«¯çsocket管éè¿æ¥ã
Socket socket = new Socket("127.0.0.1", 8080);
// 2.ä»socketé信管éä¸å¾å°ä¸ä¸ªåèè¾åºæµ
OutputStream os = socket.getOutputStream();
// 3.æä½çº§çåèè¾åºæµå
è£
æé«çº§çæå°æµã
PrintStream ps = new PrintStream(os);
// 4.å¼å§åæ¶æ¯åºå»
ps.println("ææ¯å®¢æ·ç«¯");
ps.flush();//ä¸è¬ä¸å
³éIOæµ
System.out.println("客æ·ç«¯åé宿¯~~~~");
}
}
public class ServerDemo{
public static void main(String[] args) throws Exception {
System.out.println("----æå¡ç«¯å¯å¨----");
// 1.注å端å£: public ServerSocket(int port)
ServerSocket serverSocket = new ServerSocket(8080);
// 2.å¼å§çå¾
æ¥æ¶å®¢æ·ç«¯çSocket管éè¿æ¥ã
Socket socket = serverSocket.accept();
// 3.ä»socketé信管éä¸å¾å°ä¸ä¸ªåèè¾å
¥æµã
InputStream is = socket.getInputStream();
// 4.æåèè¾å
¥æµè½¬æ¢æå符è¾å
¥æµ
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// 6.æç
§è¡è¯»åæ¶æ¯ ã
String line;
if((line = br.readLine()) != null){
System.out.println(line);
}
}
}
````
éæ±äºï¼å®¢æ·ç«¯å¯ä»¥åå¤åéæ°æ®ï¼æå¡ç«¯å¯ä»¥å夿°æ®
```java
public class ClientDemo {
public static void main(String[] args) throws Exception {
// 1.客æ·ç«¯è¦è¯·æ±äºæå¡ç«¯çsocket管éè¿æ¥ã
Socket socket = new Socket("127.0.0.1",8080);
// 2.ä»socketé信管éä¸å¾å°ä¸ä¸ªåèè¾åºæµ
OutputStream os = socket.getOutputStream();
// 3.æä½çº§çåèè¾åºæµå
è£
æé«çº§çæå°æµã
PrintStream ps = new PrintStream(os);
// 4.å¼å§åæ¶æ¯åºå»
while(true){
Scanner sc = new Scanner(System.in);
System.out.print("请说ï¼");
ps.println(sc.nextLine());
ps.flush();
}
}
}
public class ServerDemo{
public static void main(String[] args) throws Exception {
System.out.println("----æå¡ç«¯å¯å¨----");
// 1.注å端å£: public ServerSocket(int port)
ServerSocket serverSocket = new ServerSocket(8080);
// 2.å¼å§çå¾
æ¥æ¶å®¢æ·ç«¯çSocket管éè¿æ¥ã
Socket socket = serverSocket.accept();
// 3.ä»socketé信管éä¸å¾å°ä¸ä¸ªåèè¾å
¥æµã
InputStream is = socket.getInputStream();
// 4.æåèè¾å
¥æµè½¬æ¢æå符è¾å
¥æµ
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// 6.æç
§è¡è¯»åæ¶æ¯ ã
String line;
while((line = br.readLine()) != null){
System.out.println(line);
}
}
}
```
éæ±ä¸ï¼å®ç°ä¸ä¸ªæå¡ç«¯å¯ä»¥åæ¶æ¥æ¶å¤ä¸ªå®¢æ·ç«¯çæ¶æ¯
```java
public class ClientDemo {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("127.0.0.1",8080);
OutputStream os = new socket.getOutputStream();
PrintStream ps = new PrintStream(os);
while(true){
Scanner sc = new Scanner(System.in);
System.out.print("请说ï¼");
ps.println(sc.nextLine());
ps.flush();
}
}
}
public class ServerDemo{
public static void main(String[] args) throws Exception {
System.out.println("----æå¡ç«¯å¯å¨----");
ServerSocket serverSocket = new ServerSocket(8080);
while(true){
// å¼å§çå¾
æ¥æ¶å®¢æ·ç«¯çSocket管éè¿æ¥ã
Socket socket = serverSocket.accept();
// æ¯æ¥æ¶å°ä¸ä¸ªå®¢æ·ç«¯å¿
须为è¿ä¸ªå®¢æ·ç«¯ç®¡éåé
ä¸ä¸ªç¬ç«ççº¿ç¨æ¥å¤çä¸ä¹éä¿¡ã
new ServerReaderThread(socket).start();
}
}
}
class ServerReaderThread extends Thread{
privat Socket socket;
public ServerReaderThread(Socket socket){this.socket = socket;}
@Override
public void run() {
try(InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is))
){
String line;
while((line = br.readLine()) != null){
sout(socket.getRemoteSocketAddress() + ":" + line);
}
}catch(Exception e){
sout(socket.getRemoteSocketAddress() + "ä¸çº¿äº~~~~~~");
}
}
}
```
***
##### ä¼ªå¼æ¥
ä¸ä¸ªå®¢æ·ç«¯è¦ä¸ä¸ªçº¿ç¨ï¼å¹¶åè¶é«ç³»ç»ç«çªçè¶å¿«ï¼å¯ä»¥å¨æå¡ç«¯å¼å
¥çº¿ç¨æ± ï¼ä½¿ç¨çº¿ç¨æ± æ¥å¤çä¸å®¢æ·ç«¯çæ¶æ¯éä¿¡
* ä¼å¿ï¼ä¸ä¼å¼èµ·ç³»ç»çæ»æºï¼å¯ä»¥æ§å¶å¹¶å线ç¨çæ°é
* å£å¿ï¼åæ¶å¯ä»¥å¹¶åç线ç¨å°åå°éå¶
```java
public class BIOServer {
public static void main(String[] args) throws Exception {
//çº¿ç¨æ± æºå¶
//å建ä¸ä¸ªçº¿ç¨æ± ï¼å¦ææå®¢æ·ç«¯è¿æ¥ï¼å°±å建ä¸ä¸ªçº¿ç¨ï¼ä¸ä¹é讯(åç¬åä¸ä¸ªæ¹æ³)
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
//å建ServerSocket
ServerSocket serverSocket = new ServerSocket(6666);
System.out.println("æå¡å¨å¯å¨äº");
while (true) {
System.out.println("线ç¨åå = " + Thread.currentThread().getName());
//çå¬ï¼çå¾
客æ·ç«¯è¿æ¥
System.out.println("çå¾
è¿æ¥....");
final Socket socket = serverSocket.accept();
System.out.println("è¿æ¥å°ä¸ä¸ªå®¢æ·ç«¯");
//å建ä¸ä¸ªçº¿ç¨ï¼ä¸ä¹é讯
newCachedThreadPool.execute(new Runnable() {
public void run() {
//å¯ä»¥å客æ·ç«¯é讯
handler(socket);
}
});
}
}
//ç¼åä¸ä¸ªhandleræ¹æ³ï¼å客æ·ç«¯é讯
public static void handler(Socket socket) {
try {
System.out.println("线ç¨åå = " + Thread.currentThread().getName());
byte[] bytes = new byte[1024];
//éè¿socketè·åè¾å
¥æµ
InputStream inputStream = socket.getInputStream();
int len;
//循ç¯ç读å客æ·ç«¯åéçæ°æ®
while ((len = inputStream.read(bytes)) != -1) {
System.out.println("线ç¨åå = " + Thread.currentThread().getName());
//è¾åºå®¢æ·ç«¯åéçæ°æ®
System.out.println(new String(bytes, 0, read));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("å
³éåclientçè¿æ¥");
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
```
****
#### æä»¶ä¼ è¾
##### åèæµ
客æ·ç«¯ï¼æ¬å°å¾ç: âªE:\seazean\å¾çèµæº\beautiful.jpg
æå¡ç«¯ï¼æå¡å¨è·¯å¾ï¼E:\seazean\å¾çæå¡å¨
UUID. randomUUID() : æ¹æ³çæéæºçæä»¶å
**socket.shutdownOutput()**ï¼è¿ä¸ªå¿
é¡»æ§è¡ï¼ä¸ç¶æå¡å¨ä¼ä¸ç´å¾ªç¯çå¾
æ°æ®ï¼æåæä»¶æåï¼ç¨åºæ¥é
```java
//常éå
public class Constants {
public static final String SRC_IMAGE = "D:\\seazean\\å¾çèµæº\\beautiful.jpg";
public static final String SERVER_DIR = "D:\\seazean\\å¾çæå¡å¨\\";
public static final String SERVER_IP = "127.0.0.1";
public static final int SERVER_PORT = 8888;
}
public class ClientDemo {
public static void main(String[] args) throws Exception {
Socket socket = new Socket(Constants.ERVER_IP,Constants.SERVER_PORT);
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
//æåæ¬æºçå¾çä¸ä¼ ç»æå¡ç«¯ãConstants.SRC_IMAGE
BufferedInputStream bis = new BufferedInputStream(new FileInputStream());
byte[] buffer = new byte[1024];
int len ;
while((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0 ,len);
}
bos.flush();// å·æ°å¾çæ°æ®å°æå¡ç«¯ï¼ï¼
socket.shutdownOutput();// åè¯æå¡ç«¯æçæ°æ®å·²ç»åé宿¯ï¼ä¸è¦å¨çæäºï¼
bis.close();
//çå¾
çæå¡ç«¯çååºæ°æ®ï¼ï¼
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
System.out.println("æ¶å°æå¡ç«¯ååºï¼"+br.readLine());
}
}
```
```java
public class ServerDemo {
public static void main(String[] args) throws Exception {
System.out.println("----æå¡ç«¯å¯å¨----");
// 1.注å端å£:
ServerSocket serverSocket = new ServerSocket(Constants.SERVER_PORT);
// 2.å®ä¹ä¸ä¸ªå¾ªç¯ä¸æçæ¥æ¶å®¢æ·ç«¯çè¿æ¥è¯·æ±
while(true){
// 3.å¼å§çå¾
æ¥æ¶å®¢æ·ç«¯çSocket管éè¿æ¥ã
Socket socket = serverSocket.accept();
// 4.æ¯æ¥æ¶å°ä¸ä¸ªå®¢æ·ç«¯å¿
须为è¿ä¸ªå®¢æ·ç«¯ç®¡éåé
ä¸ä¸ªç¬ç«ççº¿ç¨æ¥å¤çä¸ä¹éä¿¡ã
new ServerReaderThread(socket).start();
}
}
}
class ServerReaderThread extends Thread{
private Socket socket ;
public ServerReaderThread(Socket socket){this.socket = socket;}
@Override
public void run() {
try{
InputStream is = socket.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream
(Constants.SERVER_DIR+UUID.randomUUID().toString()+".jpg"));
byte[] buffer = new byte[1024];
int len;
while((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
bos.close();
System.out.println("æå¡ç«¯æ¥æ¶å®æ¯äºï¼");
// 4.ååºæ°æ®ç»å®¢æ·ç«¯
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("æ¨å¥½ï¼å·²æåæ¥æ¶æ¨ä¸ä¼ çå¾çï¼");
ps.flush();
Thread.sleep(10000);
}catch (Exception e){
sout(socket.getRemoteSocketAddress() + "ä¸çº¿äº");
}
}
}
```
****
##### æ°æ®æµ
æé æ¹æ³ï¼
* `DataOutputStream(OutputStream out)` : å建ä¸ä¸ªæ°çæ°æ®è¾åºæµï¼ä»¥å°æ°æ®åå
¥æå®çåºå±è¾åºæµ
* `DataInputStream(InputStream in) ` : åå»ºä½¿ç¨æå®çåºå± InputStream ç DataInputStream
常ç¨APIï¼
* `final void writeUTF(String str)` : ä½¿ç¨æºå¨æ å
³çæ¹å¼ä½¿ç¨ UTF-8 ç¼ç å°å符串åå
¥åºå±è¾åºæµ
* `final String readUTF()` : 读å以 modified UTF-8 æ ¼å¼ç¼ç ç Unicode å符串ï¼è¿å String ç±»å
```java
public class Client {
public static void main(String[] args) {
InputStream is = new FileInputStream("path");
// 1ã请æ±ä¸æå¡ç«¯çSocket龿¥
Socket socket = new Socket("127.0.0.1" , 8888);
// 2ãæåèè¾åºæµå
è£
æä¸ä¸ªæ°æ®è¾åºæµ
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
// 3ãå
åéä¸ä¼ æä»¶çåç¼ç»æå¡ç«¯
dos.writeUTF(".png");
// 4ãææä»¶æ°æ®åéç»æå¡ç«¯è¿è¡æ¥æ¶
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) > 0 ){
dos.write(buffer , 0 , len);
}
dos.flush();
Thread.sleep(10000);
}
}
public class Server {
public static void main(String[] args) {
ServerSocket ss = new ServerSocket(8888);
Socket socket = ss.accept();
// 1ãå¾å°ä¸ä¸ªæ°æ®è¾å
¥æµè¯»å客æ·ç«¯åéè¿æ¥çæ°æ®
DataInputStream dis = new DataInputStream(socket.getInputStream());
// 2ã读å客æ·ç«¯åéè¿æ¥çæä»¶ç±»å
String suffix = dis.readUTF();
// 3ãå®ä¹ä¸ä¸ªåèè¾åºç®¡éè´è´£æå®¢æ·ç«¯åæ¥çæä»¶æ°æ®ååºå»
OutputStream os = new FileOutputStream("path"+
UUID.randomUUID().toString()+suffix);
// 4ã仿°æ®è¾å
¥æµä¸è¯»åæä»¶æ°æ®ï¼ååºå°åèè¾åºæµä¸å»
byte[] buffer = new byte[1024];
int len;
while((len = dis.read(buffer)) > 0){
os.write(buffer,0, len);
}
os.close();
System.out.println("æå¡ç«¯æ¥æ¶æä»¶ä¿åæåï¼");
}
}
```
***
## NIO
### åºæ¬ä»ç»
**NIOçä»ç»**ï¼
Java NIOï¼New IOãJava non-blocking IOï¼ï¼ä» Java 1.4 çæ¬å¼å§å¼å
¥çä¸ä¸ªæ°ç IO APIï¼å¯ä»¥æ¿ä»£æ åç Java IO APIï¼NIO æ¯æé¢åç¼å²åºçãåºäºééç IO æä½ï¼ä»¥æ´å é«æçæ¹å¼è¿è¡æä»¶ç读åæä½
* NIO æä¸å¤§æ ¸å¿é¨åï¼**Channelï¼ééï¼ï¼Bufferï¼ç¼å²åºï¼ï¼Selectorï¼éæ©å¨ï¼**
* NIO æ¯éé»å¡ IOï¼ä¼ ç» IO ç read å write åªè½é»å¡æ§è¡ï¼çº¿ç¨å¨è¯»å IO æé´ä¸è½å¹²å
¶ä»äºæ
ï¼æ¯å¦è°ç¨ socket.accept()ï¼å¦ææå¡å¨æ²¡ææ°æ®ä¼ è¾è¿æ¥ï¼çº¿ç¨å°±ä¸ç´é»å¡ï¼è NIO ä¸å¯ä»¥é
ç½® Socket 为éé»å¡æ¨¡å¼
* NIO å¯ä»¥åå°ç¨ä¸ä¸ªçº¿ç¨æ¥å¤çå¤ä¸ªæä½çãå设æ 1000 个请æ±è¿æ¥ï¼æ ¹æ®å®é
æ
åµå¯ä»¥åé
20 æè
80 ä¸ªçº¿ç¨æ¥å¤çï¼ä¸åä¹åçé»å¡ IO 飿 ·åé
1000 个
NIO å BIO çæ¯è¾ï¼
* BIO 以æµçæ¹å¼å¤çæ°æ®ï¼è NIO 以åçæ¹å¼å¤çæ°æ®ï¼å I/O çæçæ¯æµ I/O é«å¾å¤
* BIO æ¯é»å¡çï¼NIO 忝éé»å¡ç
* BIO åºäºåèæµåå符æµè¿è¡æä½ï¼è NIO åºäº Channel å Buffer è¿è¡æä½ï¼æ°æ®ä»éé读åå°ç¼å²åºä¸ï¼æè
ä»ç¼å²åºåå
¥å°ééä¸ãSelector ç¨äºçå¬å¤ä¸ªééçäºä»¶ï¼æ¯å¦ï¼è¿æ¥è¯·æ±ï¼æ°æ®å°è¾¾çï¼ï¼å æ¤ä½¿ç¨å个线ç¨å°±å¯ä»¥çå¬å¤ä¸ªå®¢æ·ç«¯éé
| NIO | BIO |
| ------------------------- | ------------------- |
| é¢åç¼å²åºï¼Bufferï¼ | é¢åæµï¼Streamï¼ |
| éé»å¡ï¼Non Blocking IOï¼ | é»å¡IO(Blocking IO) |
| éæ©å¨ï¼Selectorsï¼ | |
***
### å®ç°åç
NIO ä¸å¤§æ ¸å¿é¨åï¼Channel (éé)ãBuffer (ç¼å²åº)ãSelector (éæ©å¨)
* Buffer ç¼å²åº
ç¼å²åºæ¬è´¨æ¯ä¸åå¯ä»¥åå
¥æ°æ®ãè¯»åæ°æ®çå
åï¼**åºå±æ¯ä¸ä¸ªæ°ç»**ï¼è¿åå
å被å
è£
æ NIO Buffer 对象ï¼å¹¶ä¸æä¾äºæ¹æ³ç¨æ¥æä½è¿åå
åï¼ç¸æ¯è¾ç´æ¥å¯¹æ°ç»çæä½ï¼Buffer ç API æ´å 容ææä½å管ç
* Channel éé
Java NIO çéé类似æµï¼ä¸åçæ¯æ¢å¯ä»¥ä»ééä¸è¯»åæ°æ®ï¼åå¯ä»¥åæ°æ®å°ééï¼æµç读åé常æ¯ååçï¼ééå¯ä»¥éé»å¡è¯»åååå
¥ééï¼æ¯æè¯»åæåå
¥ç¼å²åºï¼ä¹æ¯æå¼æ¥å°è¯»å
* Selector éæ©å¨
Selector æ¯ä¸ä¸ª Java NIO ç»ä»¶ï¼è½å¤æ£æ¥ä¸ä¸ªæå¤ä¸ª NIO ééï¼å¹¶ç¡®å®åªäºééå·²ç»åå¤å¥½è¿è¡è¯»åæåå
¥ï¼è¿æ ·ä¸ä¸ªåç¬ç线ç¨å¯ä»¥ç®¡çå¤ä¸ª channelï¼ä»è管çå¤ä¸ªç½ç»è¿æ¥ï¼æé«æç
NIO çå®ç°æ¡æ¶ï¼

* æ¯ä¸ª Channel 对åºä¸ä¸ª Buffer
* ä¸ä¸ªçº¿ç¨å¯¹åº Selector ï¼ ä¸ä¸ª Selector 对åºå¤ä¸ª Channelï¼è¿æ¥ï¼
* ç¨åºåæ¢å°åªä¸ª Channel æ¯ç±äºä»¶å³å®çï¼Event æ¯ä¸ä¸ªéè¦çæ¦å¿µ
* Selector 伿 ¹æ®ä¸åçäºä»¶ï¼å¨å个ééä¸åæ¢
* Buffer æ¯ä¸ä¸ªå
åå ï¼ åºå±æ¯ä¸ä¸ªæ°ç»
* æ°æ®ç读ååå
¥æ¯éè¿ Buffer 宿ç , BIO ä¸è¦ä¹æ¯è¾å
¥æµï¼æè
æ¯è¾åºæµï¼ä¸è½ååï¼NIO ç Buffer æ¯å¯ä»¥è¯»ä¹å¯ä»¥åï¼ flip() 忢 Buffer ç工使¨¡å¼
Java NIO ç³»ç»çæ ¸å¿å¨äºï¼ééåç¼å²åºï¼éé表示æå¼ç IO 设å¤ï¼ä¾å¦ï¼æä»¶ã 奿¥åï¼çè¿æ¥ãè¥è¦ä½¿ç¨ NIO ç³»ç»ï¼è·åç¨äºè¿æ¥ IO 设å¤çéé以åç¨äºå®¹çº³æ°æ®çç¼å²åºï¼ç¶åæä½ç¼å²åºï¼å¯¹æ°æ®è¿è¡å¤çãç®èè¨ä¹ï¼Channel è´è´£ä¼ è¾ï¼ Buffer è´è´£ååæ°æ®
***
### ç¼å²åº
#### åºæ¬ä»ç»
ç¼å²åºï¼Bufferï¼ï¼ç¼å²åºæ¬è´¨ä¸æ¯ä¸ä¸ª**å¯ä»¥è¯»åæ°æ®çå
åå**ï¼ç¨äºç¹å®åºæ¬æ°æ®ç±»åç容å¨ï¼ç¨äºä¸ NIO ééè¿è¡äº¤äºï¼æ°æ®æ¯ä»éé读å
¥ç¼å²åºï¼ä»ç¼å²åºåå
¥ééä¸ç

**Buffer åºå±æ¯ä¸ä¸ªæ°ç»**ï¼å¯ä»¥ä¿åå¤ä¸ªç¸åç±»åçæ°æ®ï¼æ ¹æ®æ°æ®ç±»åä¸å ï¼æä»¥ä¸ Buffer 常ç¨åç±»ï¼ByteBufferãCharBufferãShortBufferãIntBufferãLongBufferãFloatBufferãDoubleBuffer
***
#### åºæ¬å±æ§
* 容éï¼capacityï¼ï¼ä½ä¸ºä¸ä¸ªå
ååï¼Buffer å
·æåºå®å¤§å°ï¼ç¼å²åºå®¹éä¸è½ä¸ºè´ï¼å¹¶ä¸å建åä¸è½æ´æ¹
* éå¶ ï¼limitï¼ï¼è¡¨ç¤ºç¼å²åºä¸å¯ä»¥æä½æ°æ®ç大å°ï¼limit åæ°æ®ä¸è½è¿è¡è¯»åï¼ï¼ç¼å²åºçéå¶ä¸è½ä¸ºè´ï¼å¹¶ä¸ä¸è½å¤§äºå
¶å®¹éãåå
¥æ¨¡å¼ï¼limit çäº buffer ç容éï¼è¯»å模å¼ä¸ï¼limit çäºåå
¥çæ°æ®é
* ä½ç½®ï¼positionï¼ï¼**ä¸ä¸ä¸ªè¦è¯»åæåå
¥çæ°æ®çç´¢å¼**ï¼ç¼å²åºçä½ç½®ä¸è½ä¸ºè´ï¼å¹¶ä¸ä¸è½å¤§äºå
¶éå¶
* æ è®°ï¼markï¼ä¸éç½®ï¼resetï¼ï¼æ è®°æ¯ä¸ä¸ªç´¢å¼ï¼éè¿ Buffer ä¸ç mark() æ¹æ³æå® Buffer ä¸ä¸ä¸ªç¹å®çä½ç½®ï¼å¯ä»¥éè¿è°ç¨ reset() æ¹æ³æ¢å¤å°è¿ä¸ª position
* ä½ç½®ãéå¶ã容ééµå®ä»¥ä¸ä¸åå¼ï¼ **0 <= position <= limit <= capacity**
***
#### 常ç¨API
`static XxxBuffer allocate(int capacity)`ï¼å建ä¸ä¸ªå®¹é为 capacity ç XxxBuffer 对象
Buffer åºæ¬æä½ï¼
| æ¹æ³ | 说æ |
| ------------------------------------------- | ------------------------------------------------------------ |
| public Buffer clear() | æ¸
空ç¼å²åºï¼ä¸æ¸
空å
容ï¼å°ä½ç½®è®¾ç½®ä¸ºé¶ï¼éå¶è®¾ç½®ä¸ºå®¹é |
| public Buffer flip() | 翻转ç¼å²åºï¼å°ç¼å²åºççé设置为å½åä½ç½®ï¼position ç½® 0 |
| public int capacity() | è¿å Bufferç capacity å¤§å° |
| public final int limit() | è¿å Buffer ççé limit çä½ç½® |
| public Buffer limit(int n) | 设置ç¼å²åºçé为 n |
| public Buffer mark() | 卿¤ä½ç½®å¯¹ç¼å²åºè®¾ç½®æ è®° |
| public final int position() | è¿åç¼å²åºçå½åä½ç½® position |
| public Buffer position(int n) | 设置ç¼å²åºçå½åä½ç½®ä¸ºn |
| public Buffer reset() | å°ä½ç½® position é置为å
å mark æ è®°çä½ç½® |
| public Buffer rewind() | å°ä½ç½®è®¾ä¸ºä¸º 0ï¼åæ¶è®¾ç½®ç mark |
| public final int remaining() | è¿åå½åä½ç½® position å limit ä¹é´çå
ç´ ä¸ªæ° |
| public final boolean hasRemaining() | 夿ç¼å²åºä¸æ¯å¦è¿æå
ç´ |
| public static ByteBuffer wrap(byte[] array) | å°ä¸ä¸ªåèæ°ç»å
è£
å°ç¼å²åºä¸ |
| abstract ByteBuffer asReadOnlyBuffer() | å建ä¸ä¸ªæ°çåªè¯»åèç¼å²åº |
| public abstract ByteBuffer compact() | ç¼å²åºå½åä½ç½®ä¸å
¶éå¶ï¼å¦ææï¼ä¹é´çåè被å¤å¶å°ç¼å²åºçå¼å¤´ |
Buffer æ°æ®æä½ï¼
| æ¹æ³ | 说æ |
| ------------------------------------------------- | ----------------------------------------------- |
| public abstract byte get() | 读å该ç¼å²åºå½åä½ç½®çå个åèï¼ç¶åä½ç½® + 1 |
| public ByteBuffer get(byte[] dst) | 读åå¤ä¸ªåèå°åèæ°ç» dst ä¸ |
| public abstract byte get(int index) | 读åæå®ç´¢å¼ä½ç½®çåèï¼ä¸ç§»å¨ position |
| public abstract ByteBuffer put(byte b) | å°ç»å®å个åèåå
¥ç¼å²åºçå½åä½ç½®ï¼position+1 |
| public final ByteBuffer put(byte[] src) | å° src åèæ°ç»åå
¥ç¼å²åºçå½åä½ç½® |
| public abstract ByteBuffer put(int index, byte b) | å°æå®åèåå
¥ç¼å²åºçç´¢å¼ä½ç½®ï¼ä¸ç§»å¨ position |
æç¤ºï¼"\n"ï¼å ç¨ä¸¤ä¸ªåè
****
#### è¯»åæ°æ®
ä½¿ç¨ Buffer è¯»åæ°æ®ä¸è¬éµå¾ªä»¥ä¸å个æ¥éª¤ï¼
* åå
¥æ°æ®å° Buffer
* è°ç¨ flip()æ¹æ³ï¼è½¬æ¢ä¸ºè¯»å模å¼
* ä» Buffer ä¸è¯»åæ°æ®
* è°ç¨ buffer.clear() æ¹æ³æ¸
é¤ç¼å²åºï¼ä¸æ¯æ¸
ç©ºäºæ°æ®ï¼åªæ¯éç½®æéï¼
```java
public class TestBuffer {
@Test
public void test(){
String str = "seazean";
//1. åé
ä¸ä¸ªæå®å¤§å°çç¼å²åº
ByteBuffer buffer = ByteBuffer.allocate(1024);
System.out.println("-----------------allocate()----------------");
System.out.println(bufferf.position());//0
System.out.println(buffer.limit());//1024
System.out.println(buffer.capacity());//1024
//2. å©ç¨ put() åå
¥æ°æ®å°ç¼å²åºä¸
buffer.put(str.getBytes());
System.out.println("-----------------put()----------------");
System.out.println(bufferf.position());//7
System.out.println(buffer.limit());//1024
System.out.println(buffer.capacity());//1024
//3. åæ¢è¯»åæ°æ®æ¨¡å¼
buffer.flip();
System.out.println("-----------------flip()----------------");
System.out.println(buffer.position());//0
System.out.println(buffer.limit());//7
System.out.println(buffer.capacity());//1024
//4. å©ç¨ get() 读åç¼å²åºä¸çæ°æ®
byte[] dst = new byte[buffer.limit()];
buffer.get(dst);
System.out.println(dst.length);
System.out.println(new String(dst, 0, dst.length));
System.out.println(buffer.position());//7
System.out.println(buffer.limit());//7
//5. clear() : æ¸
空ç¼å²åº. 使¯ç¼å²åºä¸çæ°æ®ä¾ç¶åå¨ï¼ä½æ¯å¤äºâ被éå¿âç¶æ
System.out.println(buffer.hasRemaining());//true
buffer.clear();
System.out.println(buffer.hasRemaining());//true
System.out.println("-----------------clear()----------------");
System.out.println(buffer.position());//0
System.out.println(buffer.limit());//1024
System.out.println(buffer.capacity());//1024
}
}
```
****
#### ç²å
æå
ç½ç»ä¸æå¤æ¡æ°æ®åéç»æå¡ç«¯ï¼æ°æ®ä¹é´ä½¿ç¨ \n è¿è¡åéï¼ä½è¿äºæ°æ®å¨æ¥æ¶æ¶ï¼è¢«è¿è¡äºéæ°ç»å
```java
// Hello,world\n
// I'm zhangsan\n
// How are you?\n
------ > é»å
ï¼åå
// Hello,world\nI'm zhangsan\nHo
// w are you?\n
```
```java
public static void main(String[] args) {
ByteBuffer source = ByteBuffer.allocate(32);
// 11 24
source.put("Hello,world\nI'm zhangsan\nHo".getBytes());
split(source);
source.put("w are you?\nhaha!\n".getBytes());
split(source);
}
private static void split(ByteBuffer source) {
source.flip();
int oldLimit = source.limit();
for (int i = 0; i < oldLimit; i++) {
if (source.get(i) == '\n') {
// æ ¹æ®æ°æ®çé¿åº¦è®¾ç½®ç¼å²åº
ByteBuffer target = ByteBuffer.allocate(i + 1 - source.position());
// 0 ~ limit
source.limit(i + 1);
target.put(source); // ä»source 读ï¼å target å
// debugAll(target); è®¿é® buffer çæ¹æ³
source.limit(oldLimit);
}
}
// 访é®è¿çæ°æ®å¤å¶å°å¼å¤´
source.compact();
}
```
****
### ç´æ¥å
å
#### åºæ¬ä»ç»
Byte Buffer æä¸¤ç§ç±»åï¼ä¸ç§æ¯åºäºç´æ¥å
åï¼ä¹å°±æ¯éå å
åï¼ï¼å¦ä¸ç§æ¯éç´æ¥å
åï¼ä¹å°±æ¯å å
åï¼
Direct Memory ä¼ç¹ï¼
* Java ç NIO åºå
许 Java ç¨åºä½¿ç¨ç´æ¥å
åï¼ä½¿ç¨ native 彿°ç´æ¥åé
å å¤å
å
* **è¯»åæ§è½é«**ï¼è¯»åé¢ç¹çåºåå¯è½ä¼èè使ç¨ç´æ¥å
å
* 大大æé« IO æ§è½ï¼é¿å
äºå¨ Java å å native å æ¥åå¤å¶æ°æ®
ç´æ¥å
å缺ç¹ï¼
* ä¸è½ä½¿ç¨å
æ ¸ç¼å²åº Page Cache çç¼åä¼å¿ï¼æ æ³ç¼åæè¿è¢«è®¿é®çæ°æ®å使ç¨é¢è¯»åè½
* åé
åæ¶ææ¬è¾é«ï¼ä¸å JVM å
ååæ¶ç®¡ç
* å¯è½å¯¼è´ OutOfMemoryError å¼å¸¸ï¼OutOfMemoryError: Direct buffer memory
* åæ¶ä¾èµ System.gc() çè°ç¨ï¼ä½è¿ä¸ªè°ç¨ JVM ä¸ä¿è¯æ§è¡ãä¹ä¸ä¿è¯ä½æ¶æ§è¡ï¼è¡ä¸ºæ¯ä¸å¯æ§çãç¨åºä¸è¬éè¦èªè¡ç®¡çï¼æå¯¹å»è°ç¨ mallocãfree
åºç¨åºæ¯ï¼
- ä¼ è¾å¾å¤§çæ°æ®æä»¶ï¼æ°æ®ççå½å¨æå¾é¿ï¼å¯¼è´ Page Cache 没æèµ·å°ç¼åçä½ç¨ï¼ä¸è¬éç¨ç´æ¥ IO çæ¹å¼
- éåé¢ç¹ç IO æä½ï¼æ¯å¦ç½ç»å¹¶ååºæ¯
æ°æ®æµçè§åº¦ï¼
* éç´æ¥å
åçä½ç¨é¾ï¼æ¬å° IO â å
æ ¸ç¼å²åºâ ç¨æ·ï¼JVMï¼ç¼å²åº âå
æ ¸ç¼å²åº â æ¬å° IO
* ç´æ¥å
åæ¯ï¼æ¬å° IO â ç´æ¥å
å â æ¬å° IO
JVM ç´æ¥å
åå¾è§£ï¼
***
#### éä¿¡åç
å å¤å
åä¸å JVM GC æ§å¶ï¼å¯ä»¥ä½¿ç¨å å¤å
åè¿è¡éä¿¡ï¼é²æ¢ GC åç¼å²åºä½ç½®åçååçæ
åµ
NIO 使ç¨ç SocketChannel 乿¯ä½¿ç¨çå å¤å
åï¼æºç è§£æï¼
* SocketChannel#write(java.nio.ByteBuffer) â SocketChannelImpl#write(java.nio.ByteBuffer)
```java
public int write(ByteBuffer var1) throws IOException {
do {
var3 = IOUtil.write(this.fd, var1, -1L, nd);
} while(var3 == -3 && this.isOpen());
}
```
* IOUtil#write(java.io.FileDescriptor, java.nio.ByteBuffer, long, sun.nio.ch.NativeDispatcher)
```java
static int write(FileDescriptor var0, ByteBuffer var1, long var2, NativeDispatcher var4) {
// ã夿æ¯å¦æ¯ç´æ¥å
åï¼æ¯åç´æ¥ååºï¼ä¸æ¯åå°è£
å°ç´æ¥å
åã
if (var1 instanceof DirectBuffer) {
return writeFromNativeBuffer(var0, var1, var2, var4);
} else {
//....
// ä»å å
bufferæ·è´å°å å¤buffer
ByteBuffer var8 = Util.getTemporaryDirectBuffer(var7);
var8.put(var1);
//...
// ä»å å¤åå°å
æ ¸ç¼å²åº
int var9 = writeFromNativeBuffer(var0, var8, var2, var4);
}
}
```
* 读æä½ç¸å
***
#### åé
åæ¶
ç´æ¥å
åå建 Buffer 对象ï¼`static XxxBuffer allocateDirect(int capacity)`
DirectByteBuffer æºç åæï¼
```java
DirectByteBuffer(int cap) {
//....
long base = 0;
try {
// åé
ç´æ¥å
å
base = unsafe.allocateMemory(size);
}
// å
åèµå¼
unsafe.setMemory(base, size, (byte) 0);
if (pa && (base % ps != 0)) {
address = base + ps - (base & (ps - 1));
} else {
address = base;
}
// åå»ºåæ¶å½æ°
cleaner = Cleaner.create(this, new Deallocator(base, size, cap));
}
private static class Deallocator implements Runnable {
public void run() {
unsafe.freeMemory(address);
//...
}
}
```
**åé
ååæ¶åç**ï¼
* 使ç¨äº Unsafe 对象ç allocateMemory æ¹æ³å®æç´æ¥å
åçåé
ï¼setMemory æ¹æ³å®æèµå¼
* ByteBuffer çå®ç°ç±»å
é¨ï¼ä½¿ç¨äº Cleanerï¼èå¼ç¨ï¼æ¥çæµ ByteBuffer 对象ï¼ä¸æ¦ ByteBuffer 对象被åå¾åæ¶ï¼é£ä¹ ReferenceHandler 线ç¨éè¿ Cleaner ç clean æ¹æ³è°ç¨ Deallocator ç runæ¹æ³ï¼æåéè¿ freeMemory æ¥éæ¾ç´æ¥å
å
```java
/**
* ç´æ¥å
ååé
çåºå±åçï¼Unsafe
*/
public class Demo1_27 {
static int _1Gb = 1024 * 1024 * 1024;
public static void main(String[] args) throws IOException {
Unsafe unsafe = getUnsafe();
// åé
å
å
long base = unsafe.allocateMemory(_1Gb);
unsafe.setMemory(base, _1Gb, (byte) 0);
System.in.read();
// éæ¾å
å
unsafe.freeMemory(base);
System.in.read();
}
public static Unsafe getUnsafe() {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
return unsafe;
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
```
****
#### å
±äº«å
å
FileChannel æä¾ map æ¹æ³è¿å MappedByteBuffer å¯¹è±¡ï¼ææä»¶æ å°å°å
åï¼é常æ
åµå¯ä»¥æ å°æ´ä¸ªæä»¶ï¼å¦ææä»¶æ¯è¾å¤§ï¼å¯ä»¥è¿è¡å段æ å°ï¼å®ææ å°å对ç©çå
åçæä½ä¼è¢«**忥**å°ç¡¬çä¸
FileChannel ä¸çæå屿§ï¼
* MapMode.modeï¼å
åæ åæä»¶è®¿é®çæ¹å¼ï¼å
±ä¸ç§ï¼
* `MapMode.READ_ONLY`ï¼åªè¯»ï¼ä¿®æ¹å¾å°çç¼å²åºå°å¯¼è´æåºå¼å¸¸
* `MapMode.READ_WRITE`ï¼è¯»/åï¼å¯¹ç¼å²åºçæ´æ¹æç»å°åå
¥æä»¶ï¼ä½æ¤æ¬¡ä¿®æ¹å¯¹æ å°å°å䏿件çå
¶ä»ç¨åºä¸ä¸å®æ¯å¯è§
* `MapMode.PRIVATE`ï¼ç§ç¨ï¼å¯è¯»å¯åï¼ä½æ¯ä¿®æ¹çå
容ä¸ä¼åå
¥æä»¶ï¼åªæ¯ buffer èªèº«çæ¹å
* `public final FileLock lock()`ï¼è·åæ¤æä»¶ééçæä»é
MappedByteBufferï¼å¯ä»¥è®©æä»¶å¨ç´æ¥å
åï¼å å¤å
åï¼ä¸è¿è¡ä¿®æ¹ï¼è¿ç§æ¹å¼å«å**å
åæ å°**ï¼å¯ä»¥ç´æ¥è°ç¨ç³»ç»åºå±çç¼åï¼æ²¡æ JVM å OS ä¹é´çå¤å¶æä½ï¼æé«äºä¼ è¾æçï¼ä½ç¨ï¼
* **å¯ä»¥ç¨äºè¿ç¨é´çéä¿¡ï¼è½è¾¾å°å
±äº«å
å页çä½ç¨**ï¼ä½å¨é«å¹¶åä¸è¦å¯¹æä»¶å
åè¿è¡å éï¼é²æ¢åºç°è¯»åå
容混乱åä¸ä¸è´æ§ï¼Java æä¾äºæä»¶é FileLockï¼ä½å¨ç¶/åè¿ç¨ä¸éå®åå¦ä¸è¿ç¨ä¼ä¸ç´çå¾
ï¼æçä¸é«
* 读åé£äºå¤ªå¤§èä¸è½æ¾è¿å
åä¸çæä»¶ï¼**åæ®µæ å°**
MappedByteBuffer è¾ä¹ ByteBuffer æ°å¢çä¸ä¸ªæ¹æ³ï¼
- `final MappedByteBuffer force()`ï¼ç¼å²åºæ¯ READ_WRITE 模å¼ä¸ï¼å¯¹ç¼å²åºå
容çä¿®æ¹**强å¶åå
¥æä»¶**
- `final MappedByteBuffer load()`ï¼å°ç¼å²åºçå
容载å
¥ç©çå
åï¼å¹¶è¿å该ç¼å²åºçå¼ç¨
- `final boolean isLoaded()`ï¼å¦æç¼å²åºçå
容å¨ç©çå
åä¸ï¼åè¿åçï¼å¦åè¿åå
```java
public class MappedByteBufferTest {
public static void main(String[] args) throws Exception {
// è¯»åæ¨¡å¼
RandomAccessFile ra = new RandomAccessFile("1.txt", "rw");
// è·å对åºçéé
FileChannel channel = ra.getChannel();
/**
* åæ°1 FileChannel.MapMode.READ_WRITE 使ç¨çè¯»åæ¨¡å¼
* åæ°2 0: æä»¶æ å°æ¶çèµ·å§ä½ç½®
* åæ°3 5: æ¯æ å°å°å
åç大å°ï¼ä¸æ¯ç´¢å¼ä½ç½®ï¼ï¼å³å° 1.txt çå¤å°ä¸ªåèæ å°å°å
å
* å¯ä»¥ç´æ¥ä¿®æ¹çèå´å°±æ¯ 0-5
* å®é
ç±»å DirectByteBuffer
*/
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 5);
buffer.put(0, (byte) 'H');
buffer.put(3, (byte) '9');
buffer.put(5, (byte) 'Y'); //IndexOutOfBoundsException
ra.close();
System.out.println("ä¿®æ¹æå~~");
}
}
```
ä»ç¡¬çä¸å°æä»¶è¯»å
¥å
åï¼è¦ç»è¿æä»¶ç³»ç»è¿è¡æ°æ®æ·è´ï¼æ·è´æä½æ¯ç±æä»¶ç³»ç»å硬件驱å¨å®ç°ãéè¿å
åæ å°çæ¹æ³è®¿é®ç¡¬çä¸çæä»¶ï¼æ·è´æ°æ®çæçè¦æ¯ read å write ç³»ç»è°ç¨é«ï¼
- read() æ¯ç³»ç»è°ç¨ï¼é¦å
å°æä»¶ä»ç¡¬çæ·è´å°å
æ ¸ç©ºé´çä¸ä¸ªç¼å²åºï¼åå°è¿äºæ°æ®æ·è´å°ç¨æ·ç©ºé´ï¼å®é
ä¸è¿è¡äºä¸¤æ¬¡æ°æ®æ·è´
- mmap() 乿¯ç³»ç»è°ç¨ï¼ä½æ²¡æè¿è¡æ°æ®æ·è´ï¼å½ç¼ºé¡µä¸æåçæ¶ï¼ç´æ¥å°æä»¶ä»ç¡¬çæ·è´å°å
±äº«å
åï¼åªè¿è¡äºä¸æ¬¡æ°æ®æ·è´
注æï¼mmap çæä»¶æ å°ï¼å¨ Full GC æ¶æä¼è¿è¡éæ¾ï¼å¦æéè¦æå¨æ¸
é¤å
åæ å°æä»¶ï¼å¯ä»¥åå°è°ç¨ sun.misc.Cleaner æ¹æ³
åèæç« ï¼https://www.jianshu.com/p/f90866dcbffc
***
### éé
#### åºæ¬ä»ç»
ééï¼Channelï¼ï¼è¡¨ç¤º IO æºä¸ç®æ æå¼çè¿æ¥ï¼Channel 类似äºä¼ ç»çæµï¼åªä¸è¿ Channel æ¬èº«ä¸è½ç´æ¥è®¿é®æ°æ®ï¼Channel åªè½ä¸ Buffer **è¿è¡äº¤äº**
1. NIO çééç±»ä¼¼äºæµï¼ä½æäºåºå«å¦ä¸ï¼
* ééå¯ä»¥åæ¶è¿è¡è¯»åï¼èæµåªè½è¯»æè
åªè½å
* ééå¯ä»¥å®ç°å¼æ¥è¯»åæ°æ®
* ééå¯ä»¥ä»ç¼å²è¯»æ°æ®ï¼ä¹å¯ä»¥åæ°æ®å°ç¼å²
2. BIO ä¸ç Stream æ¯ååçï¼NIO ä¸ç Channel æ¯ååçï¼å¯ä»¥è¯»æä½ï¼ä¹å¯ä»¥åæä½
3. Channel å¨ NIO 䏿¯ä¸ä¸ªæ¥å£ï¼`public interface Channel extends Closeable{}`
Channel å®ç°ç±»ï¼
* FileChannelï¼ç¨äºè¯»åãåå
¥ãæ å°åæä½æä»¶çééï¼**åªè½å·¥ä½å¨é»å¡æ¨¡å¼ä¸**
* éè¿ FileInputStream è·åç Channel åªè½è¯»
* éè¿ FileOutputStream è·åç Channel åªè½å
* éè¿ RandomAccessFile æ¯å¦è½è¯»åæ ¹æ®æé RandomAccessFile æ¶çè¯»åæ¨¡å¼å³å®
* DatagramChannelï¼éè¿ UDP 读åç½ç»ä¸çæ°æ®éé
* SocketChannelï¼éè¿ TCP 读åç½ç»ä¸çæ°æ®
* ServerSocketChannelï¼å¯ä»¥**çå¬**æ°è¿æ¥ç TCP è¿æ¥ï¼å¯¹æ¯ä¸ä¸ªæ°è¿æ¥çè¿æ¥é½ä¼å建ä¸ä¸ª SocketChannel
æç¤ºï¼ServerSocketChanne 类似 ServerSocketãSocketChannel 类似 Socket
***
#### 常ç¨API
è·å Channel æ¹å¼ï¼
* å¯¹æ¯æééç对象è°ç¨ `getChannel()` æ¹æ³
* éè¿ééçéææ¹æ³ `open()` æå¼å¹¶è¿åæå®éé
* ä½¿ç¨ Files ç±»çéææ¹æ³ `newByteChannel()` è·ååèéé
Channel åºæ¬æä½ï¼**读å齿¯ç¸å¯¹äºå
忥çï¼ä¹å°±æ¯ç¼å²åº**
| æ¹æ³ | 说æ |
| ------------------------------------------ | -------------------------------------------------------- |
| public abstract int read(ByteBuffer dst) | ä» Channel ä¸è¯»åæ°æ®å° ByteBufferï¼ä» position å¼å§å¨å |
| public final long read(ByteBuffer[] dsts) | å° Channel ä¸çæ°æ®åæ£å° ByteBuffer[] |
| public abstract int write(ByteBuffer src) | å° ByteBuffer ä¸çæ°æ®åå
¥ Channelï¼ä» position å¼å§ååº |
| public final long write(ByteBuffer[] srcs) | å° ByteBuffer[] å°ä¸çæ°æ®èéå° Channel |
| public abstract long position() | è¿åæ¤ééçæä»¶ä½ç½® |
| FileChannel position(long newPosition) | 设置æ¤ééçæä»¶ä½ç½® |
| public abstract long size() | è¿åæ¤ééçæä»¶çå½åå¤§å° |
**SelectableChannel çæä½ API**ï¼
| æ¹æ³ | 说æ |
| -------------------------------------------------------- | ------------------------------------------------------------ |
| SocketChannel accept() | 妿ééå¤äºéé»å¡æ¨¡å¼ï¼æ²¡æè¯·æ±è¿æ¥æ¶æ¤æ¹æ³å°ç«å³è¿å NULLï¼å¦åå°é»å¡ç´å°ææ°çè¿æ¥æåç I/O é误ï¼**éè¿è¯¥æ¹æ³è¿åç奿¥åééå°å¤äºé»å¡æ¨¡å¼** |
| SelectionKey register(Selector sel, int ops) | å°ééæ³¨åå°éæ©å¨ä¸ï¼å¹¶æå®çå¬äºä»¶ |
| SelectionKey register(Selector sel, int ops, Object att) | å°ééæ³¨åå°éæ©å¨ä¸ï¼å¹¶å¨å½åéé**ç»å®ä¸ä¸ªé件对象**ï¼Object 代表å¯ä»¥æ¯ä»»ä½ç±»å |
****
#### æä»¶è¯»å
```java
public class ChannelTest {
@Test
public void write() throws Exception{
// 1ãåèè¾åºæµéåç®æ æä»¶
FileOutputStream fos = new FileOutputStream("data01.txt");
// 2ãå¾å°åèè¾åºæµå¯¹åºçéé ãFileChannelã
FileChannel channel = fos.getChannel();
// 3ãåé
ç¼å²åº
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put("hello,é»é©¬Javaç¨åºåï¼".getBytes());
// 4ãæç¼å²åºåæ¢æååºæ¨¡å¼
buffer.flip();
channel.write(buffer);
channel.close();
System.out.println("åæ°æ®å°æä»¶ä¸ï¼");
}
@Test
public void read() throws Exception {
// 1ãå®ä¹ä¸ä¸ªæä»¶åèè¾å
¥æµä¸æºæä»¶æ¥é
FileInputStream fis = new FileInputStream("data01.txt");
// 2ãéè¦å¾å°æä»¶åèè¾å
¥æµçæä»¶éé
FileChannel channel = fis.getChannel();
// 3ãå®ä¹ä¸ä¸ªç¼å²åº
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 4ãè¯»åæ°æ®å°ç¼å²åº
channel.read(buffer);
buffer.flip();
// 5ã读ååºç¼å²åºä¸çæ°æ®å¹¶è¾åºå³å¯
String rs = new String(buffer.array(),0,buffer.remaining());
System.out.println(rs);
}
}
```
***
#### æä»¶å¤å¶
Channel çæ¹æ³ï¼**sendfile å®ç°é¶æ·è´**
* `abstract long transferFrom(ReadableByteChannel src, long position, long count)`ï¼ä»ç»å®çå¯è¯»åèééå°åèä¼ è¾å°è¯¥ééçæä»¶ä¸
* srcï¼æºéé
* positionï¼æä»¶ä¸è¦è¿è¡ä¼ è¾çä½ç½®ï¼å¿
é¡»æ¯éè´ç
* countï¼è¦ä¼ è¾çæå¤§åèæ°ï¼å¿
é¡»æ¯éè´ç
* `abstract long transferTo(long position, long count, WritableByteChannel target)`ï¼å°è¯¥ééæä»¶çåèä¼ è¾å°ç»å®çå¯ååèééã
* positionï¼ä¼ è¾å¼å§çæä»¶ä¸çä½ç½®; å¿
é¡»æ¯éè´ç
* countï¼è¦ä¼ è¾çæå¤§åèæ°; å¿
é¡»æ¯éè´ç
* targetï¼ç®æ éé
æä»¶å¤å¶çä¸¤ç§æ¹å¼ï¼
1. Buffer
2. 使ç¨ä¸è¿°ä¸¤ç§æ¹æ³

```java
public class ChannelTest {
@Test
public void copy1() throws Exception {
File srcFile = new File("C:\\å£çº¸.jpg");
File destFile = new File("C:\\Users\\å£çº¸new.jpg");
// å¾å°ä¸ä¸ªåèåèè¾å
¥æµ
FileInputStream fis = new FileInputStream(srcFile);
// å¾å°ä¸ä¸ªåèè¾åºæµ
FileOutputStream fos = new FileOutputStream(destFile);
// å¾å°çæ¯æä»¶éé
FileChannel isChannel = fis.getChannel();
FileChannel osChannel = fos.getChannel();
// åé
ç¼å²åº
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(true){
// å¿
é¡»å
æ¸
空ç¼å²ç¶åååå
¥æ°æ®å°ç¼å²åº
buffer.clear();
// å¼å§è¯»å䏿¬¡æ°æ®
int flag = isChannel.read(buffer);
if(flag == -1){
break;
}
// å·²ç»è¯»åäºæ°æ® ï¼æç¼å²åºç模å¼åæ¢æå¯è¯»æ¨¡å¼
buffer.flip();
// ææ°æ®ååºå°
osChannel.write(buffer);
}
isChannel.close();
osChannel.close();
System.out.println("å¤å¶å®æï¼");
}
@Test
public void copy02() throws Exception {
// 1ãåèè¾å
¥ç®¡é
FileInputStream fis = new FileInputStream("data01.txt");
FileChannel isChannel = fis.getChannel();
// 2ãåèè¾åºæµç®¡é
FileOutputStream fos = new FileOutputStream("data03.txt");
FileChannel osChannel = fos.getChannel();
// 3ãå¤å¶
osChannel.transferFrom(isChannel,isChannel.position(),isChannel.size());
isChannel.close();
osChannel.close();
}
@Test
public void copy03() throws Exception {
// 1ãåèè¾å
¥ç®¡é
FileInputStream fis = new FileInputStream("data01.txt");
FileChannel isChannel = fis.getChannel();
// 2ãåèè¾åºæµç®¡é
FileOutputStream fos = new FileOutputStream("data04.txt");
FileChannel osChannel = fos.getChannel();
// 3ãå¤å¶
isChannel.transferTo(isChannel.position() , isChannel.size() , osChannel);
isChannel.close();
osChannel.close();
}
}
```
***
#### 忣èé
åæ£è¯»åï¼Scatter ï¼ï¼æ¯ææ Channel ééçæ°æ®è¯»å
¥å°å¤ä¸ªç¼å²åºä¸å»
èéåå
¥ï¼Gathering ï¼ï¼æ¯æå°å¤ä¸ª Buffer ä¸çæ°æ®èéå° Channel
```java
public class ChannelTest {
@Test
public void test() throws IOException{
// 1ãåèè¾å
¥ç®¡é
FileInputStream is = new FileInputStream("data01.txt");
FileChannel isChannel = is.getChannel();
// 2ãåèè¾åºæµç®¡é
FileOutputStream fos = new FileOutputStream("data02.txt");
FileChannel osChannel = fos.getChannel();
// 3ãå®ä¹å¤ä¸ªç¼å²åºåæ°æ®åæ£
ByteBuffer buffer1 = ByteBuffer.allocate(4);
ByteBuffer buffer2 = ByteBuffer.allocate(1024);
ByteBuffer[] buffers = {buffer1 , buffer2};
// 4ãä»ééä¸è¯»åæ°æ®åæ£å°å个ç¼å²åº
isChannel.read(buffers);
// 5ã仿¯ä¸ªç¼å²åºä¸æ¥è¯¢æ¯å¦ææ°æ®è¯»åå°äº
for(ByteBuffer buffer : buffers){
buffer.flip();// 忢å°è¯»æ°æ®æ¨¡å¼
System.out.println(new String(buffer.array() , 0 , buffer.remaining()));
}
// 6ãèéåå
¥å°éé
osChannel.write(buffers);
isChannel.close();
osChannel.close();
System.out.println("æä»¶å¤å¶~~");
}
}
```
***
### éæ©å¨
#### åºæ¬ä»ç»
éæ©å¨ï¼Selectorï¼ æ¯ SelectableChannle 对象ç**å¤è·¯å¤ç¨å¨**ï¼Selector å¯ä»¥åæ¶çæ§å¤ä¸ªééçç¶åµï¼å©ç¨ Selector å¯ä½¿ä¸ä¸ªåç¬ç线ç¨ç®¡çå¤ä¸ª Channelï¼**Selector æ¯éé»å¡ IO çæ ¸å¿**

* Selector è½å¤æ£æµå¤ä¸ªæ³¨åçéé䏿¯å¦æäºä»¶åçï¼å¤ä¸ª Channel 以äºä»¶çæ¹å¼å¯ä»¥æ³¨åå°åä¸ä¸ª Selector)ï¼å¦ææäºä»¶åçï¼å°±è·åäºä»¶ç¶åé对æ¯ä¸ªäºä»¶è¿è¡ç¸åºçå¤çï¼å°±å¯ä»¥åªç¨ä¸ä¸ªå线ç¨å»ç®¡çå¤ä¸ªééï¼ä¹å°±æ¯ç®¡çå¤ä¸ªè¿æ¥å请æ±
* åªæå¨è¿æ¥/ééçæ£æè¯»åäºä»¶åçæ¶ï¼æä¼è¿è¡è¯»åï¼å°±å¤§å¤§å°åå°äºç³»ç»å¼éï¼å¹¶ä¸ä¸å¿
为æ¯ä¸ªè¿æ¥é½å建ä¸ä¸ªçº¿ç¨ï¼ä¸ç¨å»ç»´æ¤å¤ä¸ªçº¿ç¨
* é¿å
äºå¤çº¿ç¨ä¹é´çä¸ä¸æåæ¢å¯¼è´çå¼é
***
#### 常ç¨API
å建 Selectorï¼`Selector selector = Selector.open();`
å鿩卿³¨åééï¼`SelectableChannel.register(Selector sel, int ops, Object att)`
* åæ°ä¸ï¼éæ©å¨ï¼æå®å½å Channel 注åå°çéæ©å¨
* åæ°äºï¼éæ©å¨å¯¹ééççå¬äºä»¶ï¼çå¬çäºä»¶ç±»åç¨å个常é表示
* 读 : SelectionKey.OP_READ ï¼1ï¼
* å : SelectionKey.OP_WRITE ï¼4ï¼
* è¿æ¥ : SelectionKey.OP_CONNECT ï¼8ï¼
* æ¥æ¶ : SelectionKey.OP_ACCEPT ï¼16ï¼
* è¥ä¸æ¢çå¬ä¸ä¸ªäºä»¶ï¼ä½¿ç¨ä½ææä½ç¬¦è¿æ¥ï¼`int interest = SelectionKey.OP_READ | SelectionKey.OP_WRITE`
* åæ°ä¸ï¼å¯ä»¥å
³èä¸ä¸ªéä»¶ï¼å¯ä»¥æ¯ä»»ä½å¯¹è±¡
**Selector API**ï¼
| æ¹æ³ | 说æ |
| ------------------------------------------------ | ------------------------------------------- |
| public static Selector open() | æå¼éæ©å¨ |
| public abstract void close() | å
³éæ¤éæ©å¨ |
| public abstract int select() | **é»å¡**éæ©ä¸ç»ééåå¤å¥½è¿è¡ I/O æä½çé® |
| public abstract int select(long timeout) | **é»å¡**çå¾
timeout æ¯«ç§ |
| public abstract int selectNow() | è·åä¸ä¸ï¼**ä¸é»å¡**ï¼ç«å»è¿å |
| public abstract Selector wakeup() | å¤éæ£å¨é»å¡ç selector |
| public abstract Set