网络框架(bio,nio,netty,socket)

参考资料

马士兵io模型和netty原理-视频讲解
马士兵io模型和netty原理-视频讲解-视频源码
socket的原理,http原理

bio

在这里插入图片描述

socket里面的
bind()–绑定ip,端口
listen()–接受客户端的连接请求
accept()–把建立好连接的socket从就绪队列里取出来返回而已,当然了如果就绪队列为空(没有就绪连接) 则会阻塞

        ServerSocket ss = new ServerSocket();
        ss.bind(new InetSocketAddress("127.0.0.1", 8888));
        Socket s = ss.accept(); //阻塞方法[没有连接就会阻塞]
         byte[] bytes = new byte[1024];
         int len = s.getInputStream().read(bytes);  //[io读取数据会阻塞住,比如客户端只是连进来了,但并没有发数据,或者发了很大的数据,就需要一直读]
         System.out.println(new String(bytes, 0, len));
         s.getOutputStream().write(bytes, 0, len); //【客户端不接受数据,就会写不出去数据,也会阻塞住】

缺点是不能处理大量的连接

nio(单线程模型)

selector一人干了监听accept,read,write的所有事情
在这里插入图片描述

        ServerSocketChannel ssc = ServerSocketChannel.open();//它是对原来bio通道的一个封装,现在该通道可读可写,是双向的。bio需要拿到inputstream来读,outputstream来写,但现在对于nio来说ServerSocketChannel就可读可写了
        ssc.socket().bind(new InetSocketAddress("127.0.0.1", 8888));
        ssc.configureBlocking(false);

        System.out.println("server started, listening on :" + ssc.getLocalAddress());
        Selector selector = Selector.open();
        ssc.register(selector, SelectionKey.OP_ACCEPT);//注册感兴趣的事件(有客户端连上来,即accept()发生了)

        while(true) {
            selector.select();//【这是阻塞的,当事件OP_ACCEPT发生了它才会往下走】
            Set<SelectionKey> keys = selector.selectedKeys();//一个SelectionKey相当于一个想连接成功的客户端
            Iterator<SelectionKey> it = keys.iterator();
            while(it.hasNext()) {
                SelectionKey key = it.next();
                it.remove();
                handle(key);
            }}}
    private static void handle(SelectionKey key) {
        if(key.isAcceptable()) {
            try {
                ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                SocketChannel sc = ssc.accept();//给连接成功的客户端一个通道
                sc.configureBlocking(false);
                sc.register(key.selector(), SelectionKey.OP_READ );//注册一个想要读的事件
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
            }
        } else if (key.isReadable()) { //flip
            SocketChannel sc = null;
            try {
                sc = (SocketChannel)key.channel();
                ByteBuffer buffer = ByteBuffer.allocate(512);//先将字节收集到缓冲数组,再从数组中(bio是一个字节一个的读,效率低),ByteBuffer 的api很恶心,不好用,netty对此进行了优化,因此很受欢迎
                buffer.clear();
                int len = sc.read(buffer);   //读的过程不小心阻塞,(单线程的)selector整体就会阻塞
                if(len != -1) {
                    System.out.println(new String(buffer.array(), 0, len));
                }
                ByteBuffer bufferToWrite = ByteBuffer.wrap("HelloClient".getBytes());
                sc.write(bufferToWrite);  //写的过程不小心阻塞,(单线程的)selector整体就会阻塞
}

nio(响应式模型)

selector一人现在只干监听accept,将read,write的事情交给一个线程池去做。有一个accept连上来并发生了读事件,就将其丢到线程池里面去处理。
在这里插入图片描述
这里selector相当于boss,线程池相当于worker

aio

在这里插入图片描述
在这里插入图片描述

netty

netty使用的是nio模型
linux底层使用的是epoll模型(aio和nio都是epoll模型实现的),epoll本身是轮询模型,因此无论aio上层整么封装,底层实现仍是轮询(linux的aio效率未必比nio高),还不如直接nio(netty的实现的nio,但它封装的api更像是aio)

EventLoopGroup bossGroup = new NioEventLoopGroup();//线程组boss,处理连接,相当于selector,默认是1个,可指定多个线程new NioEventLoopGroup(5)
        EventLoopGroup workerGroup = new NioEventLoopGroup();//线程组worker,处理读写
        ServerBootstrap b = new ServerBootstrap();//对服务进行启动配置
        //第一个线程组负责连接,第二线程组负责连接后的线程处理
        b.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)//通道类型
                //每个客户端连上来之后,给它一个监听器进行处理(过程如下:通道上加上处理器就是一个监听器)--整样处理
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    //一旦通道初始话了
                    protected void initChannel(SocketChannel ch) throws Exception {
                    //我就给通道添加处理。通道上有个监听器队列,在队列最后位置添加处理器
                        ch.pipeline().addLast(new Handler());
                    }
                });
class Handler extends ChannelInboundHandlerAdapter {
    @Override
    //有数据上来,该方法就会被自动调用,且数据都已经读出来封装到了Object msg,都无需自己来处理数据的读
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //super.channelRead(ctx, msg);
        System.out.println("server: channel read");
        ByteBuf buf = (ByteBuf)msg;

        System.out.println(buf.toString(CharsetUtil.UTF_8));

        ctx.writeAndFlush(msg);

        ctx.close();

        //buf.release();
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值