服务端代码实现如下,其中包括一个静态内部类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

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

  1. 转载 WPF -- 控件模板 (ControlTemplate)(一) https://blog.csdn.net/qq_23018459/article/details/79899838

    ControlTemplate(控件模板)   https://blog.csdn.net/qq_23018459/article/details/79899838 WPF包含数据模板和控件模板,其中 ...

  2. 已知IP地址和子网掩码求出网络地址、广播地址、地址范围和主机数(转载https://blog.csdn.net/qq_39026548/article/details/78959089)

    假设IP地址为128.11.67.31,子网掩码是255.255.240.0.请算出网络地址.广播地址.地址范围.主机数.方法:将IP地址和子网掩码转化成二进制形式,然后进行后续操作. IP地址和子网 ...

  3. 炸天的3D引擎OpenCASCADE的用法及案例(https://blog.csdn.net/xipengbozai/article/details/117044032?spm=1001.2014.3001.5502)

    What CASCADE?Open CASCADE(简称OCC)平台是由法国Matra Datavision公司开发的CAD/CAE/CAM软件平台,可以说是世界上最重要的几何造型基础软件平台之一.开 ...

  4. 爬虫出现Forbidden by robots.txt(转载 https://blog.csdn.net/zzk1995/article/details/51628205)

    先说结论,关闭scrapy自带的ROBOTSTXT_OBEY功能,在setting找到这个变量,设置为False即可解决. 使用scrapy爬取淘宝页面的时候,在提交http请求时出现debug信息F ...

  5. Mui本地打包笔记(一)使用AndroidStudio运行项目 转载 https://blog.csdn.net/baidu_32377671/article/details/79632411

    转载 https://blog.csdn.net/baidu_32377671/article/details/79632411 使用AndroidStudio运行HBuilder本地打包的Mui项目 ...

  6. MVC和WebApi 使用get和post 传递参数。 转载https://blog.csdn.net/qq373591361/article/details/51508806

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq373591361/article/details/51508806我们总结一下用js请求服务器的 ...

  7. AutoFac控制反转 转载https://blog.csdn.net/u011301348/article/details/82256791

    一.AutoFac介绍 Autofac是.NET里IOC(Inversion of Control,控制反转)容器的一种,同类的框架还有Spring.NET,Unity,Castle等.可以通过NuG ...

  8. IntelliJ Idea 常用快捷键列表 (需整理下) https://blog.csdn.net/dc_726/article/details/42784275

    [常规] https://blog.csdn.net/dc_726/article/details/42784275https://jingyan.baidu.com/article/59a015e3 ...

  9. Postman用法简介----https://blog.csdn.net/flowerspring/article/details/52774399

    https://blog.csdn.net/flowerspring/article/details/52774399 Postman用法简介

随机推荐

  1. python序列(十)字典

    字典是无序可变序列. 定义字典是,每个元素的键和值用冒号分隔,元素之间用逗号分隔,所有的元素放在一对大括号"{ }"中. 字典中的键可以为任意不可变数据,比如.整数.实数.复数.字 ...

  2. 本地缓存性能之王Caffeine

    前言 随着互联网的高速发展,市面上也出现了越来越多的网站和app.我们判断一个软件是否好用,用户体验就是一个重要的衡量标准.比如说我们经常用的微信,打开一个页面要十几秒,发个语音要几分钟对方才能收到. ...

  3. Javascript 获得数组中相同或不同的数组元素   

    Javascript 获得数组中相同或不同的数组元素 在Javascript中,偶尔会用到获取数组中相同或不同的元素值的情况,以下提供了获得数组中相同或不同的 元素函数供参考学习使用. // 数字类型 ...

  4. 解决npm ERR!

    一:[Unexpected end of JSON input while parsing near]报错 最近的vue项目中在执行 npm install 时会报错误: npm ERR! Unexp ...

  5. 如何利用Typora编写博客,快速发布到多平台?

    在不同的平台发布同样的文章,最让人头疼的就是图片问题,如果要手动一个个去重新上传,耗时耗力,还容易搞错.下面分享的方法,可以将Typora编写的文章快速发布到CSDN.微信公众号.博客园.简书等平台. ...

  6. SQL Server 数据库还原进度查看

    SQL Server 数据库还原进度查看 关键字:数据库,还原,进度,查看 文档说明: 本文档受某实际需求启发,某约500G大小数据库还原,由于对应服务器性能较差(内存仅4G且可用内存仅2.8G),数 ...

  7. CentOS8_在线安装_网络源_网络镜像源填写格式_以及其他笔记

    CentOS8_在线安装_网络源_网络镜像源填写格式_以及其他笔记 转载注明来源: 本文链接 来自osnosn的博客,写于 2020-10-1. 参考: Centos8.0.1905 在线安装源选择 ...

  8. Linux LVM Logical Volume Management 逻辑卷的管理

    博主是一个数据库DBA,但是一般来说,是不做linux服务器LVM 逻辑卷的创建.扩容和减容操作的,基本上有系统管理员操作,一是各司其职,专业的事专业的人做,二是做多了你的责任也多了,哈哈! 但是li ...

  9. 解锁Renderbus客户端使用新技巧----快速渲染效果图篇

    度娘说,效果图最基本的要求就是:应该符合事物的本身尺寸,不能为了美观而使用效果把相关模型的尺寸变动,那样的效果图不但不能起到表现设计的作用,反而成为影响设计的一个因素.可见高效渲染效果图是都是当下我们 ...

  10. 【Maven】Maven 高级应用

    Maven 高级应用 Maven 基础 Maven 是一个项目管理工具,它有如下好处: 节省磁盘空间 可以一键构建 可以跨平台使用 依赖传递和管理,提高开发效率 一键构建:Maven 自身集成了 To ...