NIO阻塞案例讲解,为什么会阻塞和解决办法

本文深入探讨了NIO在网络编程中的应用,通过客户端与服务端的交互实例,详细解析了SocketChannel与FileChannel的配合使用,以及ByteBuffer在数据读写中的关键作用。文章强调了shutdownOutput方法的重要性,避免了因客户端持续写入状态导致的服务端无限等待问题。
摘要由CSDN通过智能技术生成
      public void client() throws IOException {
        //创建套接字通道
        SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
        //文件通道,连接文件
        FileChannel inChannel = FileChannel.open(Paths.get("1.txt"), StandardOpenOption.READ);
        //创建一个1024字节大小的缓存
        ByteBuffer buf = ByteBuffer.allocate(1024);
        //将字节序列从此通道中读入给定的缓冲区,如果通道中的数据读完了就终止循环
        while(inChannel.read(buf) != -1){
            //把缓冲当前位置指针移动到初始0位置
            buf.flip();
            //将字节序列从给定的缓冲区中写入此通道。
            sChannel.write(buf);
            //清空缓存
            buf.clear();
        }
        //为什么要使用shutdownOutput呢,如果用close,name整个通道都会关闭,包括网络连接,所以肯定不行,因为接下去还有其他操作
        //而wirte还没有关闭通道一直处于写入状态,服务端sChannel并不知道结束了,所以还一直等待客户端的输出(阻塞)
        sChannel.shutdownOutput();
        //接收服务端的反馈
        int len = 0;
        while((len = sChannel.read(buf)) != -1){
            buf.flip();
            System.out.println(new String(buf.array(), 0, len));
            buf.clear();
        }

        inChannel.close();
        sChannel.close();
    }
public void server() throws IOException {
        ServerSocketChannel ssChannel = ServerSocketChannel.open();

        FileChannel outChannel = FileChannel.open(Paths.get("2.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);

        ssChannel.bind(new InetSocketAddress(9898));

        //一直等到有客户端链接,会一直阻塞
        SocketChannel sChannel = ssChannel.accept();

        ByteBuffer buf = ByteBuffer.allocate(1024);

        //客户端若是没加sChannel.shutdownOutput();,服务端会以为客户端还在发送数据过来,所以一直等待,死循环
        //而加了sChannel.shutdownOutput(),标记输出流为-1,相当于达到末尾,这时候服务端清楚你已经不再发数据了,就会终止循环,到下一步
        //read(buf)读取的字节数,可能为零,如果该通道已到达流的末尾,则返回 -1
        while(sChannel.read(buf) != -1){
            System.out.println(111);
            buf.flip();
            outChannel.write(buf);
            buf.clear();
        }
        //发送反馈给客户端
        buf.put("服务端接收数据成功".getBytes());
        buf.flip();
        sChannel.write(buf);

        sChannel.close();
        outChannel.close();
        ssChannel.close();
    }

同时启动这俩程序

主要是客户端加这个sChannel.shutdownOutput(),不然去掉这个会死循环,服务端会一直等客户端发送数据过来,会死掉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值