NIO案例

1,NioServer.java
package com.forezp.util.io.nio.service;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.charset.Charset;

public class NioServer {
    private Selector selector;
    private ServerSocketChannel socketChannel;

    public static void main(String[] args) {
        new NioServer().bind(6000);
    }

    private void bind(int port) {
        try {
            selector=Selector.open();
            socketChannel=ServerSocketChannel.open();
            socketChannel.configureBlocking(false);
            //绑定端口
            socketChannel.socket().bind(new InetSocketAddress(port),1024);
            //注册通道
            socketChannel.register(selector, SelectionKey.OP_ACCEPT);
            System.out.println("nio server start ...");
            new NioServerHandler(selector, Charset.forName("UTF-8")).start();
        }catch (IOException e){
            e.printStackTrace();
        }


    }


}

2,NioServerHandler.java

package com.forezp.util.io.nio.service;

import com.forezp.util.io.nio.ChannelAdapter;
import com.forezp.util.io.nio.ChannelHandler;

import java.io.IOException;
import java.nio.channels.Selector;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;

public class NioServerHandler extends ChannelAdapter {


    public NioServerHandler(Selector selector, Charset charset) {
        super(selector, charset);
    }

    /***
     * 通道
     * @param ctx
     */
    @Override
    public void channelActive(ChannelHandler ctx) {

        try {
            System.out.println("LocalAddress:" + ctx.channel().getLocalAddress());
            ctx.writeAndFlush("hello,NioServer to msg for you\r\n");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /***
     * 处理信息
     * @param ctx
     * @param msg
     */
    @Override
    public void channelRead(ChannelHandler ctx, Object msg) {
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "服务端接收到消息:" + msg);
        ctx.writeAndFlush("hello,服务端已经收到你的消息Success!\r\n");
        ctx.writeAndFlush("服务端消息内容:"+msg);
    }
}

3,ChannelAdapter.java

package com.forezp.util.io.nio;



import java.io.IOException;
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.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

public  abstract class ChannelAdapter extends Thread {
    private Selector selector;
    private ChannelHandler channelHandler;
    private Charset charset;

    public ChannelAdapter(Selector selector, Charset charset) {
        this.selector = selector;
        this.charset = charset;
    }


    @Override
    public void run() {
        while (true) {
            try {
                //选择通道,设置超时时间
                selector.select(1000);
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> it = selectedKeys.iterator();
                SelectionKey key = null;
                while (it.hasNext()) {
                    key = it.next();
                    it.remove();
                    handleInput(key);
                }
            } catch (Exception ignore) {
            }
        }
    }

    /***
     * 处理接收到的消息块
     * @param key
     */
    private void handleInput(SelectionKey key) throws IOException {
        //调用key的isValid()方法来测试其有效性,无效则退出
        if (!key.isValid()) return;

        // 客户端SocketChannel
        Class<?> superclass = key.channel().getClass().getSuperclass();
        if (superclass == SocketChannel.class){
            SocketChannel socketChannel = (SocketChannel) key.channel();
            if (key.isConnectable()) {
                if (socketChannel.finishConnect()) {
                    channelHandler = new ChannelHandler(socketChannel, charset);
                    channelActive(channelHandler);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else {
                    System.exit(1);
                }
            }
        }

        // 服务端ServerSocketChannel
        if (superclass == ServerSocketChannel.class){
            if (key.isAcceptable()) {
                ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
                SocketChannel socketChannel = serverSocketChannel.accept();
                socketChannel.configureBlocking(false);
                socketChannel.register(selector, SelectionKey.OP_READ);

                channelHandler = new ChannelHandler(socketChannel, charset);
                channelActive(channelHandler);
            }
        }

        if (key.isReadable()) {
            SocketChannel socketChannel = (SocketChannel) key.channel();
            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
            int readBytes = socketChannel.read(readBuffer);
            if (readBytes > 0) {
                readBuffer.flip();
                byte[] bytes = new byte[readBuffer.remaining()];
                readBuffer.get(bytes);
                channelRead(channelHandler, new String(bytes, charset));
            } else if (readBytes < 0) {
                key.cancel();
                socketChannel.close();
            }
        }
    }


    // 链接通知
    public abstract void channelActive(ChannelHandler ctx);

    // 读取消息
    public abstract void channelRead(ChannelHandler ctx, Object msg);


}

4,ChannelHandler.java

package com.forezp.util.io.nio;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class ChannelHandler {
    private SocketChannel channel;
    private Charset charset;

    public ChannelHandler(SocketChannel channel, Charset charset) {
        this.channel = channel;
        this.charset = charset;
    }
    //获取消息
    public void writeAndFlush(Object msg) {

        try {
            byte[] bytes = msg.toString().getBytes(charset);
            ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
            writeBuffer.put(bytes);
            writeBuffer.flip();
            channel.write(writeBuffer);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public SocketChannel channel() {
        return channel;
    }


}

5,NioClient.java

package com.forezp.util.io.nio.client;

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

public class NioClient {

    public static void main(String[] args) {
        try {
            Selector selector=Selector.open();
            SocketChannel channel=SocketChannel.open();
            channel.configureBlocking(false);
            boolean isConnect=channel.connect(new InetSocketAddress("127.0.0.1",6000));
            if(isConnect){
                channel.register(selector, SelectionKey.OP_READ);
            }else {
                channel.register(selector,SelectionKey.OP_CONNECT);
            }
            new NioClientHandler(selector, Charset.forName("UTF-8")).start();

        }catch (IOException e){
            e.printStackTrace();
        }


    }
}

6,NioClientHandler.java

package com.forezp.util.io.nio.client;

import com.forezp.util.io.nio.ChannelAdapter;
import com.forezp.util.io.nio.ChannelHandler;

import java.io.IOException;
import java.nio.channels.Selector;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;

public class NioClientHandler extends ChannelAdapter {
    public NioClientHandler(Selector selector, Charset charset) {
        super(selector, charset);
    }

    @Override
    public void channelActive(ChannelHandler ctx) {
        try {
            System.out.println("LocalAddress:" + ctx.channel().getLocalAddress());
            ctx.writeAndFlush("hello,NioClient to msg for you \r\n");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void channelRead(ChannelHandler ctx, Object msg) {
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "客户端接收到消息:" + msg);
        ctx.writeAndFlush("hello,客户端已经收到你的消息Success!\r\n");
        ctx.writeAndFlush("客户端消息内容:"+msg);
    }
}

运行服务端,客户端测试:

 

netty框架学习之基础

 
 
 




























 

posted on 2022-10-09 11:26  让代码飞  阅读(39)  评论(0)    收藏  举报

导航

一款免费在线思维导图工具推荐:https://www.processon.com/i/593e9a29e4b0898669edaf7f?full_name=python