美文网首页
传统IO,NIO,netty的几种实现方式

传统IO,NIO,netty的几种实现方式

作者: dinel | 来源:发表于2020-04-16 14:36 被阅读0次

1.未使用 Netty 的阻塞网络编程

package com.nettyTest4;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;
//1.未使用 Netty 的阻塞网络编程 
public class PlainOioServer {

     public void serve(int port) throws IOException { 
         
         final ServerSocket socket = new ServerSocket(port);     
         try {           
             for (;;) {     
                 final Socket clientSocket = socket.accept();       
                 System.out.println(  "Accepted connection from " + clientSocket);   
                 new Thread(new Runnable() {       
                     @Override               
                     public void run() {          
                         OutputStream out;                  
                         try {                     
                             out = clientSocket.getOutputStream();                          
                             out.write("Hi!\r\n".getBytes( Charset.forName("UTF-8")));        
                             out.flush();                          
                             clientSocket.close();        
                             }  catch (IOException e) {     
                                 e.printStackTrace();                      
                             } finally {                      
                                 try {                        
                                     clientSocket.close();            
                                }catch (IOException ex) {         
                                         // ignore on close              
                                }                        
                            }                     
                    }               
                }).start();      
             }        
        }  catch (IOException e) {      
             e.printStackTrace();       
        }     
    } 
}

2.未使用 Netty 的异步网络编程

package com.nettyTest4;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

//2.未使用 Netty 的异步网络编程  NIO
public class PlainNioServer {

    public static void serve(int port) throws IOException{
        
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        
        serverChannel.configureBlocking(false);
        
        ServerSocket socket = serverChannel.socket();
        
        InetSocketAddress address = new InetSocketAddress(port);
        
        //将服务器绑定到端口
        socket.bind(address);
        //打开Selector 来处理Channel
        Selector selector = Selector.open();
        //将ServerSocket注册到Selector以接收连接
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        
        final ByteBuffer msg = ByteBuffer.wrap("Hi!\r\n".getBytes());
        
        for(;;){
            try{
        //等待需要处理的新事件,阻塞将一直持续到下一个传入事件
                selector.select();
            }catch(IOException ex){
                ex.printStackTrace();
                break;
            }
        }
        //获取所有接收事件的Selection Key实例
        Set<SelectionKey> readyKeys = selector.selectedKeys();
        Iterator<SelectionKey> iterator = readyKeys.iterator();
        
        while(iterator.hasNext()){
            
            SelectionKey key = iterator.next();
            iterator.remove();
            
            try{
        //检查事件是否是一个新的已经就绪可以被接受的连接
                if(key.isAcceptable()){
                    ServerSocketChannel server = (ServerSocketChannel)key.channel();
                    SocketChannel client = server.accept();
                    client.configureBlocking(false);
        //接受客户端并将它注册到选择器
                    client.register(selector, SelectionKey.OP_WRITE|SelectionKey.OP_READ, msg.duplicate());
                    System.out.println("Accepted connection from " + client);                     
                } 
        //检查套接字是否已经准备好写数据
                if(key.isWritable()){
                    SocketChannel client = (SocketChannel)key.channel();
                    ByteBuffer buffer =  (ByteBuffer)key.attachment();
                    while (buffer.hasRemaining()) {  
                        //将数据写到已经连接的客户端
                        if (client.write(buffer) == 0) { 
                            break;   
                        }                  
                    } 
        //关闭连接
                    client.close(); 
                }
            }catch(IOException es){
                 key.cancel();                    
                 try {                       
                     key.channel().close();
                 } catch (IOException cex) {                      
                     // ignore on close            
                      
                 }
            }
            
        }
        
    }
    
    public static void main(String[] args) throws IOException {
        
        serve(8080);
    }
}


3.使用 Netty 的阻塞网络处理

package com.nettyTest4;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.oio.OioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.oio.OioServerSocketChannel;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

//3.使用 Netty 的阻塞网络处理 
public class NettyOioServer {

    public void  server(int port)throws Exception{
        final ByteBuf buf  = Unpooled.unreleasableBuffer(Unpooled.copiedBuffer("Hi!\r\n", Charset.forName("UTF-8")));
        EventLoopGroup group  = new OioEventLoopGroup();
        try{
            //创建ServerBootstrap
            ServerBootstrap b= new ServerBootstrap();
            b.group(group)
            //使用OIOEventLoopGroup 允许阻塞模式(传统的BIO)
            .channel(OioServerSocketChannel.class) //该类即将被netty废弃
            .localAddress(new InetSocketAddress(port))
            //指定ChannelInitializer对于每个已接受的连接都调用它
            .childHandler(new ChannelInitializer<SocketChannel>(){
                @Override
                public void initChannel(SocketChannel ch) throws Exception{
                    
                    ch.pipeline().addLast(
                    //  添加一个ChannelInboundHandlerAdapter以拦截和处理事件
                    new ChannelInboundHandlerAdapter(){
                        @Override
                        public void channelActive(ChannelHandlerContext ctx) throws Exception{
                            ctx.writeAndFlush(buf.duplicate()).addListener(
                                //将消息写入客户端,并添加ChannelFutureListener 以便消息一被写完就关闭
                                ChannelFutureListener.CLOSE);
                        }
                    });
                }
            });
        //绑定服务器已接受连接
        ChannelFuture f = b.bind().sync();
        f.channel().closeFuture().sync();
        }finally{
            //释放所有资源
            group.shutdownGracefully().sync();
        }
    }
}


4.使用 Netty 的异步网络处理

package com.nettyTest4;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

//4.使用 Netty 的异步网络处理 
public class NettyNioServer {
    public void server(int port)throws Exception{
        final ByteBuf buf =Unpooled.copiedBuffer("Hi!\r\n",
                                    Charset.forName("UTF-8"));
        //为非阻塞模式使用NioEventLoopGroup
        EventLoopGroup group = new NioEventLoopGroup();
        try{
            //创建ServerBootstrap
            ServerBootstrap b = new ServerBootstrap();
            
            b.group(group).channel(NioServerSocketChannel.class)
            .localAddress(new InetSocketAddress(port))
            //指定ChannelInitializer 对于每个已接受的连接都调用它
            
            .childHandler(new ChannelInitializer<SocketChannel>(){
                @Override
                public void initChannel(SocketChannel ch) throws Exception{
                    
                    ch.pipeline().addLast(
                        //添加ChannelInboundHandlerAdapter 已接收和处理事件
                        new ChannelInboundHandlerAdapter(){
                            @Override
                            public void channelActive(ChannelHandlerContext ctx) throws Exception{
                                //将消息写到客户端,并添加ChannelFutureListener 以便消息一被写完就关闭连接
                                ctx.writeAndFlush(buf.duplicate()).addListener(ChannelFutureListener.CLOSE);
                            }
                    });
                }
            });
            //绑定服务器已接受资源
            ChannelFuture f = b.bind().sync();
            f.channel().closeFuture().sync();
        }finally{
            //释放所有资源
            group.shutdownGracefully().sync();
        }
    }
}


相关文章

网友评论

      本文标题:传统IO,NIO,netty的几种实现方式

      本文链接:https://www.haomeiwen.com/subject/xnmrvhtx.html