Java-NIO-Selector

来源:互联网 发布:java计算器程序 编辑:程序博客网 时间:2024/06/15 11:19

1.背景

在jdk1.4,nio引入到java中;
C/C++代码的工具箱中,许多年前就已经有 select()和 poll()这两个POSIX(可移植性操作系统接口)系统调用可供使用了。许过操作系统也提供相似的功能,但对Java 程序员来说,就绪选择功能直到 JDK 1.4 才成为可行的方案。

本文编写一个client-server小程序,都采用Selector来管理连接;

2.例子

2.1客户端

import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.IOException;import java.net.InetSocketAddress;import java.net.SocketAddress;import java.nio.ByteBuffer;import java.nio.channels.ClosedChannelException;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.SocketChannel;import java.util.Iterator;import java.util.Set;import java.util.concurrent.ArrayBlockingQueue;/** * Created by Administrator on 2017/8/10. */public class MyClient {    private static Logger logger = LoggerFactory.getLogger(MyClient.class);    private int buffsize = 512;    private ArrayBlockingQueue<String> blockingQueue = new ArrayBlockingQueue(1);    public void testClient(){        Selector selector = null;        try {            selector = Selector.open();        } catch (IOException e) {            logger.error("",e);        }        SocketChannel socketChannel = null;        try {            socketChannel = SocketChannel.open();            socketChannel.configureBlocking(false);        } catch (IOException e) {            logger.error("",e);        }        SocketAddress socketAddress = new InetSocketAddress(4444);        try {            socketChannel.connect(socketAddress);        } catch (IOException e) {            logger.error("",e);        }        try {            socketChannel.register(selector,SelectionKey.OP_CONNECT);        } catch (ClosedChannelException e) {            logger.error("",e);        }        //handle        logger.info("start");        for (;;){            try {                if(selector.select(3000) == 0 ){                    logger.info("client continue select...");                    continue;                }            } catch (IOException e) {                logger.error("",e);            }            Set<SelectionKey> selectionKeySet = selector.selectedKeys();            Iterator iterator = selectionKeySet.iterator();            while (iterator.hasNext()){                SelectionKey selectionKey = (SelectionKey) iterator.next();                if(selectionKey.isValid() && selectionKey.isConnectable()){                    socketChannel = (SocketChannel) selectionKey.channel();                    try {                        socketChannel.configureBlocking(false);                    } catch (IOException e) {                        logger.error("",e);                        try {                            socketChannel.close();                        } catch (IOException e1) {                            logger.error("",e);                        }                    }                    try {                        socketChannel.register(selector,SelectionKey.OP_READ | SelectionKey.OP_WRITE);                    } catch (ClosedChannelException e) {                        logger.error("",e);                        try {                            socketChannel.close();                        } catch (IOException e1) {                            logger.error("",e);                        }                    }                    //(作为客户端有责任)发送第一个请求                    try {                        if(socketChannel.finishConnect()){                            ByteBuffer byteBuffer = ByteBuffer.wrap("first request".getBytes());                            socketChannel = (SocketChannel) selectionKey.channel();                            try {                                socketChannel.write(byteBuffer);                            } catch (IOException e) {                                logger.error("",e);                                socketChannel.close();                            }                        }                    } catch (IOException e) {                        logger.error("",e);                    }                }                if(selectionKey.isValid() && selectionKey.isWritable()){                    socketChannel = (SocketChannel) selectionKey.channel();                    if(socketChannel.isConnected()){                        ByteBuffer byteBuffer = ByteBuffer.wrap("i'm client".getBytes());                        socketChannel = (SocketChannel) selectionKey.channel();                        try {                            socketChannel.write(byteBuffer);                        } catch (IOException e) {                            logger.error("",e);                            try {                                socketChannel.close();                            } catch (IOException e1) {                                logger.error("",e);                            }                        }                    }                }                if(selectionKey.isValid() && selectionKey.isReadable()){                    socketChannel = (SocketChannel) selectionKey.channel();                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);                    try {                        socketChannel.read(byteBuffer);                    } catch (IOException e) {                        logger.error("",e);                        try {                            socketChannel.close();                        } catch (IOException e1) {                            logger.error("",e);                        }                    }                    logger.info("" + new String(byteBuffer.array()));                    String msg = new String(byteBuffer.array());                    //进行粘包处理                    String[] arr = msg.split(";");                    String _msg = null;                    for (int i=0;i  < arr.length;i++){                        logger.info("进行粘包处理后:" + new String(arr[i]));                        //假设知道内容大小                        int size = 10;//假设知道size=10                        if(arr[i].length() < size){                            logger.info("这个信息拆包了,拆包后的内容:"+arr[i]);                            if(blockingQueue.size()!=0){                                try {                                    _msg = blockingQueue.take() + arr[i];                                    logger.info("这个信息拆包了,拆包处理后的内容:"+_msg);                                } catch (InterruptedException e) {                                    logger.error("",e);                                }                            }else{                                blockingQueue.offer(arr[i]);                            }                        }                    }                }                iterator.remove();            }        }    }}

2.2 服务端

import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.IOException;import java.net.InetSocketAddress;import java.net.SocketAddress;import java.net.SocketException;import java.nio.ByteBuffer;import java.nio.channels.*;import java.util.Iterator;import java.util.Set;/** * Created by Administrator on 2017/8/10. */public class MyServer {    private static Logger logger = LoggerFactory.getLogger(MyServer.class);    private int buffsize = 512;    public void testServer(){        Selector selector = null;        try {            selector = Selector.open();        } catch (IOException e) {            logger.error("Selector.open() occur Excetion!",e);        }        ServerSocketChannel serverSocketChannel = null;        try {            serverSocketChannel = ServerSocketChannel.open();            serverSocketChannel.configureBlocking(false);            SocketAddress socketAddress = new InetSocketAddress(4444);            serverSocketChannel.bind(socketAddress);        } catch (IOException e) {            logger.error("",e);        }        int ops = serverSocketChannel.validOps();        try {            serverSocketChannel.register(selector, ops);        } catch (ClosedChannelException e) {            logger.error("",e);        }        //handle        logger.info("start");        for (;;){            try {                if(selector.select(3000) == 0 ){                    logger.info("server continue select...");                    continue;                }            } catch (IOException e) {                logger.error("",e);            }            Set<SelectionKey> selectionKeySet =  selector.selectedKeys();            Iterator  iterator = selectionKeySet.iterator();            while (iterator.hasNext()){                SelectionKey selectionKey = (SelectionKey) iterator.next();                if(selectionKey.isValid() && selectionKey.isAcceptable()){                    serverSocketChannel = (ServerSocketChannel) selectionKey.channel();                    SocketChannel socketChannel = null;                    try {                        socketChannel = serverSocketChannel.accept();                        socketChannel.configureBlocking(false);                        int _ops = socketChannel.validOps();                        socketChannel.register(selector,_ops);                    } catch (IOException e) {                        logger.error("",e);                        try {                            socketChannel.close();                        } catch (IOException e1) {                            logger.error("",e);                        }                    }                }                if(selectionKey.isValid() && selectionKey.isReadable()){                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();                    ByteBuffer byteBuffer = ByteBuffer.allocate(10);//1024byte                    try {                        socketChannel.read(byteBuffer);                    } catch (IOException e) {                        logger.error("",e);                        try {                            socketChannel.close();                        } catch (IOException e1) {                            logger.error("",e);                        }                    }                    logger.info("" + new String(byteBuffer.array()));                }                if(selectionKey.isValid() && selectionKey.isWritable()){                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();                    try {                        socketChannel.socket().setTcpNoDelay(true);                    } catch (SocketException e) {                        logger.error("");                    }                    ByteBuffer byteBuffer = ByteBuffer.wrap("i'm server;".getBytes());                    try {                        socketChannel.write(byteBuffer);                    } catch (IOException e) {                        logger.error("",e);                        try {                            socketChannel.close();                        } catch (IOException e1) {                            logger.error("",e);                        }                    }//                    byteBuffer.flip();                }                iterator.remove();            }        }    }}

2.3 启动测试

public class MyClinetTest {    @Test    public void testClient(){        MyClient myClient = new MyClient();        myClient.testClient();    }}
public class MyServerTest {    @Test    public void testServer(){        MyServer myServer = new MyServer();        myServer.testServer();    }}
原创粉丝点击