Netty NIO 非阻塞模式2(完善)

1.概要

1.1 说明

Netty NIO 非阻塞模式-CSDN博客

真对上面的问题,做些修正。主要解决如下问题。当客户端关闭或者强制关闭的时候,服务端关闭对应的SelectionKey。这样可以避免因异常退出,和不断的重复读取数据。

1.1.1客户端强制退出,下面的代码会包异常。所以需要要try catch捕获异常,以保证服务端正常运行。因为这时候这个“SelectionKey”已经没有用了,所以也需要取消。

SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
ByteBuffer byteBuffer1 = ByteBuffer.allocate(16);
int len = socketChannel.read(byteBuffer1);

 1.1.2 客户端正常退出,会给服务端发送一次写的请求,但不写任何数据,这时候服务端可以判断客户端退出了,也删除SelectionKey”

                        if(len>0){
                            。。。略
                        }else {
                            //如果没有都到数据,取消selectionKey
                            selectionKey.channel();
                        }

2.代码

2.1 服务端

package com.xjc.springcloundtest;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.net.SocketOption;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

public class Main {
    public static void main(String[] args) throws IOException {
        ByteBuffer byteBuffer = ByteBuffer.allocate(16);
        Selector selector = Selector.open();
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        SelectionKey sscKey = ssc.register(selector,0,null);
        sscKey.interestOps(SelectionKey.OP_ACCEPT);
        ssc.bind(new InetSocketAddress(8080));
        List<SocketChannel> channels = new ArrayList<>();
        while (true){

            //如果没有事件 就阻塞
            selector.select();
            Iterator<SelectionKey> iter = selector.selectedKeys().iterator();

            while (iter.hasNext()){
                SelectionKey selectionKey = iter.next();
                iter.remove();
                if(selectionKey.isAcceptable()){
                    ServerSocketChannel ssc2 =  (ServerSocketChannel)selectionKey.channel();
                    SocketChannel sc = ssc2.accept();
                    sc.configureBlocking(false);
                    SelectionKey sckey = sc.register(selector,0,null);
                    sckey.interestOps(SelectionKey.OP_READ);
                }else if(selectionKey.isReadable()){
                    try {
                        SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
                        ByteBuffer byteBuffer1 = ByteBuffer.allocate(16);
                        int len = socketChannel.read(byteBuffer1);
                        if(len>0){
                            byteBuffer.flip();
                            while (byteBuffer.hasRemaining()){
                                byte b = byteBuffer.get();
                                System.out.println((char)b);
                            }
                            //这里也可以用下面的方式输出读到的内容
                            //System.out.println(Charset.defaultCharset().decode(byteBuffer));
                            byteBuffer.clear();
                            System.out.println("read 后");
                        }else {
                            //如果没有都到数据,取消selectionKey
                            selectionKey.channel();
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                        //如果发生异常取消selectionKey
                        selectionKey.channel();
                    }

                }

            }

            /*

            System.out.println("accept 前");
            SocketChannel sc = ssc.accept();
            System.out.println("accept 后");
            if(sc!=null){
                sc.configureBlocking(false);
                channels.add(sc);
            }
            for (SocketChannel channel: channels){
                System.out.println("read 后");
                int len = channel.read(byteBuffer);
                if(len>0){
                    byteBuffer.flip();
                    while (byteBuffer.hasRemaining()){
                        byte b = byteBuffer.get();
                        System.out.println((char)b);
                    }
                    byteBuffer.clear();
                    System.out.println("read 后");
                }
            }*/
        }
        //System.out.println("Hello world!");
    }
}

2.2 客户端

package com.xjc.springcloundtest;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class Client {
    public static void main(String[] args) throws IOException {
        SocketChannel sc = SocketChannel.open();
        sc.connect(new InetSocketAddress("localhost", 8080));
        sc.write(Charset.defaultCharset().encode("helllo"));
        System.out.println("Hello world!");
    }
}

  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值