2.1Java 阻塞式io

Java 阻塞式io

执行流程

总体流程图
OIO:线程发起IO请求,不管内核是否准备好IO操作,从发起请求起,线程一直阻塞,直到操作完成。
一个连接一个线程
2.1Java 阻塞式io

1.Server

  1. 创建连接(ServerSocketChannel)
  2. 开启端口(SocketAddress)并绑定bind()
  3. 循环监听
    1)等待请求连接serversocketchannel.accept() 【发生阻塞】
    2)每个SocketChannel开启线程读取数据。

2.Client

  1. 开启socketChannel
  2. 创建连接socketChannel.connect(地址,端口)
  3. 开始发送和接受数据。

代码

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
2.1Java 阻塞式io
client
2.1Java 阻塞式io

阻塞io的缺点

  1. 每次连接都要新开线程(accept()方法开线程处理。)
  2. accept() 是一个阻塞操作,