### 介紹

### 同步IO之BlockingIO

如上圖所示,用戶進程process在Blocking IO讀recvfrom操作的兩個階段都是等待的。在數據沒準備好的時候,process原地等待kernel準備數據。kernel準備好數據后,process繼續等待kernel將數據copy到自己的buffer。在kernel完成數據的copy后process才會從recvfrom系統調用中返回
### 同步阻塞式I/O
```
public class SocketServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8999);
while (true) {
Socket socket = server.accept();
new Thread(new ChannelSocker(socket)).start();
}
}
static class ChannelSocker implements Runnable {
private Socket socket;
public ChannelSocker(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
StringBuffer res = new StringBuffer();
try (InputStream inputStream = socket.getInputStream();
InputStreamReader reader = new InputStreamReader(inputStream);
BufferedReader read = new BufferedReader(reader);) {
String line = read.readLine();
while (line != null) {
res.append(line);
line = read.readLine();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
System.err.println("接收到消息" + res.toString());
}
}
}
}
```
阻塞型I/O,主要阻塞在兩個地方:
1. 在調用InutStream.read方法是阻塞的,它會一直等到數據到來時(或超時)才會返回;
2. 在調用ServerSocket.accept方法時,也會一直阻塞到有客戶端連接才會返回;
### setSoTimeout
serverSocket.setSoTimeout\(3000\); \#\# soTimeout將accept阻塞3秒
Socket socket = serverSocket.accept\(\);
```
try (ServerSocket serverSocket = new ServerSocket(8089)){
serverSocket.setSoTimeout(3000);
Socket socket = serverSocket.accept();
System.err.println("finished");
} catch (Exception e) {
e.printStackTrace();
}
System.err.println("end==>");
```
### SO\_RCVBUF
SO\_RCVBUF選項設置了服務器Socket接受的客戶端Socket默認緩沖區大小
```
try (ServerSocket serverSocket = new ServerSocket(8089)){
serverSocket.setSoTimeout(3000);
serverSocket.setReceiveBufferSize(1024);
Socket socket = serverSocket.accept();
System.err.println("finished");
} catch (Exception e) {
e.printStackTrace();
}
System.err.println("end==>");
```
### 阻塞模型

### 阻塞型的I/O存在的問題
InputStream.read\(\)方法在其緩存區未滿時會造成阻塞,只有數據填滿了緩存區或者客戶端關閉了套接字,方法才會返回;
BufferedReader創建了緩存區來從套接字中讀入數據,但是同樣創建了一些字符串存儲這些數據,這些String很快變成垃圾需要回收;
InputStream 中的read方法用于讀取數據,方法有3個重載:
* read\(\):從輸入流讀取下一個數據字節;
* read\(byte\[\] b\):從輸入流中讀取一定數量的字節并將其存儲在緩沖區數組b中;
* read\(byte\[\] b, int off, int len\):將輸入流中最多 len 個數據字節讀入字節數組;
- 概述
- Netty&Tomcat的區別
- NIO基礎知識
- 同步阻塞式IO
- 偽異步IO編程
- 同步IO之IO-multiplexing
- NIO基礎概念
- NIO服務流程
- Netty基礎知識
- NettyServer開發示例
- 零拷貝
- TCP粘包和拆包問題
- LineBasedFrameDecoder&StringDecoder
- 應用層消息處理方式
- ByteBuf
- ChannelHandler
- Netty核心組件
- Channel接口
- ChannelHandler
- ChannelInboundHandlerAdapter
- SimpleChannelInboundHandler
- SimpleChannelInboundHandler && ChannelInboundHandler
- ChannelInitializer
- EventLoop接口
- ChannelFuture接口
- ChannelPipeline接口
- 序列化
- JAVA序列化