zoukankan      html  css  js  c++  java
  • Socket的用法——NIO包下SocketChannel的用法 ———————————————— 版权声明:本文为CSDN博主「茶_小哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/ycgslh/article/details/79604074

    服务端代码实现如下,其中包括一个静态内部类Handler来作为处理器,处理不同的操作。注意在遍历选择键集合时,没处理完一个操作,要将该请求在集合中移除。
    /*
    模拟服务端-nio-Socket实现
    */
    public class NIOServer {
        public static void main(String[] args) {
            try {
                //创建ServerSocketChannel通道,绑定监听端口为8080
                ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
                serverSocketChannel.socket().bind(new InetSocketAddress(8080));
                //设置为非阻塞模式
                serverSocketChannel.configureBlocking(false);
                //注册选择器,设置选择器选择的操作类型
                Selector selector = Selector.open();
                serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
                //创建处理器
                Handler handler = new Handler(1204);
                while (true) {
                    //等待请求,每次等待阻塞3s,超过时间则向下执行,若传入0或不传值,则在接收到请求前一直阻塞
                    if (selector.select(3000) == 0) {
                        System.out.println("等待请求超时......");
                        continue;
                    }
                    System.out.println("-----处理请求-----");
                    //获取待处理的选择键集合
                    Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
                    while (keyIterator.hasNext()) {
                        SelectionKey selectionKey = keyIterator.next();
                        try {
                            //如果是连接请求,调用处理器的连接处理方法
                            if(selectionKey.isAcceptable()){
                                handler.handleAccept(selectionKey);
                            }
                            //如果是读请求,调用对应的读方法
                            if (selectionKey.isReadable()) {
                                handler.handleRead(selectionKey);
                            }
                        } catch (IOException e) {
                            keyIterator.remove();
                            continue;
                        }
                    }
                    //处理完毕从待处理集合移除该选择键
                    keyIterator.remove();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

        /*
            处理器类
        */
        private static class Handler{
            private int bufferSize = 1024; //缓冲器容量
            private String localCharset = "UTF-8"; //编码格式

            public Handler(){}
            public Handler(int bufferSize){
                this(bufferSize,null);
            }
            public Handler(String localCharset){
                this(-1,localCharset);
            }
            public Handler(int bufferSize,String localCharset){
                if(bufferSize > 0){
                    this.bufferSize = bufferSize;
                }
                if(localCharset != null){
                    this.localCharset = localCharset;
                }
            }
            /*
            连接请求处理方法
            */
            public void handleAccept(SelectionKey selectionKey) throws IOException {
                //通过选择器键获取服务器套接字通道,通过accept()方法获取套接字通道连接
                SocketChannel socketChannel = ((ServerSocketChannel)selectionKey.channel()).accept();
                //设置套接字通道为非阻塞模式
                socketChannel.configureBlocking(false);
                //为套接字通道注册选择器,该选择器为服务器套接字通道的选择器,即选择到该SocketChannel的选择器
                //设置选择器关心请求为读操作,设置数据读取的缓冲器容量为处理器初始化时候的缓冲器容量
                socketChannel.register(selectionKey.selector(),SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize));
            }

            public void handleRead(SelectionKey selectionKey) throws IOException {
                //获取套接字通道
                SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                //获取缓冲器并进行重置,selectionKey.attachment()为获取选择器键的附加对象
                ByteBuffer byteBuffer = (ByteBuffer)selectionKey.attachment();
                byteBuffer.clear();
                //没有内容则关闭通道
                if (socketChannel.read(byteBuffer) == -1) {
                    socketChannel.close();
                } else {
                    //将缓冲器转换为读状态
                    byteBuffer.flip();
                    //将缓冲器中接收到的值按localCharset格式编码保存
                    String receivedRequestData = Charset.forName(localCharset).newDecoder().decode(byteBuffer).toString();
                    System.out.println("接收到客户端的请求数据:"+receivedRequestData);
                    //返回响应数据给客户端
                    String responseData = "已接收到你的请求数据,响应数据为:(响应数据)";
                    byteBuffer = ByteBuffer.wrap(responseData.getBytes(localCharset));
                    socketChannel.write(byteBuffer);
                    //关闭通道
                    socketChannel.close();
                }
            }
        }
    }
    ————————————————
    版权声明:本文为CSDN博主「茶_小哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/ycgslh/article/details/79604074

  • 相关阅读:
    系统维护相关问题
    Python环境维护
    哈希表解决字符串问题
    论文笔记二:《A Tutoral on Spectral Clustering》
    论文笔记之哈希学习比较--《Supervised Hashing with Kernels》《Towards Optimal Binary Code Learning via Ordinal Embedding》《Top Rank Supervised Binary Coding for Visual Search》
    Java中String、StringBuffer、StringBuilder的比较与源 代码分析
    浙大pat1040 Longest Symmetric String(25 分)
    浙大pat1039 Course List for Student(25 分)
    浙大pat---1036 Boys vs Girls (25)
    百炼oj-4151:电影节
  • 原文地址:https://www.cnblogs.com/jishumonkey/p/12955487.html
Copyright © 2011-2022 走看看