2.1Java 阻塞式io
Java 阻塞式io
执行流程
总体流程图
OIO:线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成。
一个连接一个线程
1.Server
- 创建连接(ServerSocketChannel)
- 开启端口(SocketAddress)并绑定bind()
- 循环监听
1)等待请求连接serversocketchannel.accept() 【发生阻塞】
2)每个SocketChannel开启线程读取数据。
2.Client
- 开启socketChannel
- 创建连接socketChannel.connect(地址,端口)
- 开始发送和接受数据。
代码
Server
public class Server {
public static void main(String[] args) throws IOException {
// 开启Socket
ServerSocketChannel serversocketchannel = ServerSocketChannel.open();
// 开启端口
SocketAddress socketAddress = new InetSocketAddress(8080);
// 监听8080 端口进来的tcp连接
serversocketchannel.socket().bind(socketAddress);
// 开启循环监听
while(true){
// 这里会阻塞,直到有请求连接
SocketChannel socketChannel = serversocketchannel.accept();
// 开启新的线程来处理这个请求,然后while循环监听8080端口
SocketHandler handler = new SocketHandler(socketChannel);
new Thread(handler).start();
}
}
}
SocketHandler处理数据
public class SocketHandler implements Runnable{
private SocketChannel socketChannel;
public SocketHandler(SocketChannel socketChannel){
this.socketChannel = socketChannel;
}
public void run() {
// 堆空间中分配缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
try {
// 将请求数据读入Buffer中
int num ;
// 如果有数据
while ((num = socketChannel.read(buffer))>0){
// 读取Buffer内容之前先flip一下
// Buffer 切换为读模式
buffer.flip();
// 加快读取速度
byte[] bytes = new byte[num];
// 读取数据
buffer.get(bytes);
String result = new String (bytes,"UTF-8");
System.out.println("收到请求:"+result);
// 回复客户端
// warp用于存放在byte数组
ByteBuffer writeBuffer = ByteBuffer.wrap(("我已经收到你的请求,你的请求内容是:" + result).getBytes());
socketChannel.write(writeBuffer);
buffer.clear();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
client
public class Client {
public static void main(String[] args) {
try {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("localhost",8080));
// 发送请求
ByteBuffer buffer = ByteBuffer.wrap("test".getBytes());
socketChannel.write(buffer);
// 获取server响应
ByteBuffer readBuffer = ByteBuffer.allocate(1024);
int num ;
if((num = socketChannel.read(readBuffer))> 0 ){
readBuffer.flip();
byte[] result = new byte[num];
readBuffer.get(result);
String demo = new String(result,"UTF-8");
System.out.println("返回值:"+demo);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
结果展示和分析
运行结构
Server
client
阻塞io的缺点
- 每次连接都要新开线程(accept()方法开线程处理。)
- accept() 是一个阻塞操作,