Java传统IO / NIO基础知识

1.IO的基本操作

只线程情况下只能有一个客户端的连接

package xss.netty.basicio;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * java 原生的IO处理方式
 * IO Server
 */
public class IOMainServerTest {

    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket=new ServerSocket(9999);
        System.out.println("server start.......");
        while (true){
            // 会阻塞client的连接,只到client的消息处理完
            //也就是说一次只能处理一个客户端的请求
            Socket socket=serverSocket.accept();
            System.out.println("new client connect");
            handler(socket);
        }
    }

    public static  void handler(Socket socket) {
        try{
            InputStream inputStream=socket.getInputStream();
            byte[] readBytes=new byte[1024];
            while(true){
                int reads =inputStream.read(readBytes);//阻塞数据的读取
                if(reads != -1){
                    System.out.println("message ->"+new String(readBytes,0,reads));
                }else{
                    break;
                }
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            try {
                System.out.println("socket closed.");
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

可多客户端的同时连接

package xss.netty.basicio;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * java 原生的IO处理方式
 *  改进之一:服务端可以同时接收多个客户端的请求
 *
 */
public class IOMainServerMutliClientTest {

    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket=new ServerSocket(9999);
        System.out.println("server start.......");
        ExecutorService  executors= Executors.newCachedThreadPool();
        while (true){
            // 会阻塞client的连接,只到client的消息处理完
            //也就是说一次只能处理一个客户端的请求
            final Socket socket=serverSocket.accept();
            System.out.println("new client connect");
            executors.execute(new Runnable() {
                public void run() {
                    handler(socket);
                }
            });
        }
    }

    public static  void handler(Socket socket) {
        try{
            InputStream inputStream=socket.getInputStream();
            byte[] readBytes=new byte[1024];
            while(true){
                int reads =inputStream.read(readBytes);//阻塞数据的读取
                if(reads != -1){
                    System.out.println("message ->"+new String(readBytes,0,reads));
                }else{
                    break;
                }
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            try {
                System.out.println("socket closed.");
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

2.NIO的基本操作

package xss.netty.basicio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * NIO 基本知识点
 */
public class NIOMainServerTest {
    //通道的管理,监听客户发送的事件
    private Selector selector;

    public static void main(String[] args) throws  Exception{
        NIOMainServerTest serverTest=new NIOMainServerTest();
        serverTest.initServer(9999);
        serverTest.listen();
        System.out.println("main executed.");
    }

    /**
     * 初始化ServerSocket 通道
     * @param port
     * @throws IOException
     */
    public void initServer(int port) throws IOException{
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
        //设置为非阻塞通道
        serverSocketChannel.configureBlocking(false);
        //绑定端口
        serverSocketChannel.socket().bind(new InetSocketAddress(port));
        //
        this.selector=Selector.open();
        //将selector 与 通道进行绑定,并且注册ACCEPT事件
        //selector会阻塞监听是否有ACCEPT事件的到达。Selector.select()
        serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
        System.out.println("Server init finished with prot="+port);
    }

    /**
     * 轮询监听selector上是否有需要处理的事件
     * @throws IOException
     */
    public void listen() throws  IOException{
        System.out.println("start listen...");
        while (true){
            //当注册的事件到达时,方法返回;否则,该方法会一直阻塞
            selector.select();
            //获得selector中选中的项的迭代器,选中的项为注册的事件
            Iterator iterator=this.selector.selectedKeys().iterator();
            while(iterator.hasNext()){
                SelectionKey selectionKey=(SelectionKey)iterator.next();
                iterator.remove();//删除已选的key,以防重复处理
                //处理请求
                this.handler(selectionKey);
            }
        }
    }
    /**
     * 事件类型请求的处理
     * @param key
     * @throws IOException
     */
    public void handler(SelectionKey key) throws  IOException{
        if(key.isAcceptable()){
            //客户端的连接请求事件
            handlerAccept(key);
        }else  if(key.isReadable()){
            //处理客户端发送的数据
            handelerRead(key);
        }
    }

    public void handlerAccept(SelectionKey key) throws IOException {
        ServerSocketChannel serverSocketChannel=(ServerSocketChannel) key.channel();
        //建立与客户端连接的通道
        SocketChannel channel=serverSocketChannel.accept();
        channel.configureBlocking(false);
        //给selector 绑定客户端,并且监听客户端发送的请求。即对于服务端来说是可读取到客户端的数据
        //请求
        channel.register(this.selector,SelectionKey.OP_READ);
        System.out.println("New Client connected");
    }

    public void handelerRead(SelectionKey key) throws IOException {
        SocketChannel channel=(SocketChannel)key.channel();
        //缓冲区的大小以实际情况来调整
        ByteBuffer byteBuffer= ByteBuffer.allocate(1024);
        //读取数据, -- 示例客户端最大一次性发送1024
        int read=channel.read(byteBuffer);
        if(read>0){
            String readMsg=new String(byteBuffer.array());
            System.out.println("Read message:"+readMsg);
            //响应客户端
            ByteBuffer outBuffer=ByteBuffer.wrap((readMsg+" is Ok").getBytes());
            channel.write(outBuffer);
        }else{
            System.out.println("client closed.");
            key.cancel();
        }
    }
}

操作系统IO Selector 模型类似

猜你喜欢

转载自blog.csdn.net/seanme/article/details/83044636