Java NIO实例

一个可运行的简单NIO实例,首先是一个抽象的服务端类AbstractNIOServer

 

public abstract class AbstractNIOServer implements Runnable {

    // 要监听的端口号
    protected int port;
    // 生成一个信号监视器
    protected Selector s;

    public AbstractNIOServer(int port) {
        this.port = port;
        try {
            s = Selector.open();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            // 生成一个ServerScoket通道的实例对象,用于侦听可能发生的IO事件
            ServerSocketChannel ssc = ServerSocketChannel.open();
            // 将该通道设置为异步方式
            ssc.configureBlocking(false);
            // 绑定到一个指定的端口
            ssc.socket().bind(new InetSocketAddress(port));
            // 注册特定类型的事件到信号监视器上
            ssc.register(s, SelectionKey.OP_ACCEPT);
            System.out.println("The server has been launched...");
            while (true) {
                // 将会阻塞执行,直到有事件发生
                s.select();
                Iterator<SelectionKey> it = s.selectedKeys().iterator();
                while (it.hasNext()) {
                    SelectionKey key = it.next();
                    // key定义了四种不同形式的操作
                    switch (key.readyOps()) {
                        case SelectionKey.OP_ACCEPT:
                            dealwithAccept(key);
                            break;
                        case SelectionKey.OP_CONNECT:
                            break;
                        case SelectionKey.OP_READ:
                            dealwithRead(key);
                            break;
                        case SelectionKey.OP_WRITE:
                            break;
                    }
                    // 处理结束后移除当前事件,以免重复处理
                    it.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 处理接收连接的事件
    public abstract void dealwithAccept(SelectionKey key);

    // 处理客户端发来的消息,处理读事件
    public abstract void dealwithRead(SelectionKey key);

}

 服务端实现类SynServer

 

class SynServer extends AbstractNIOServer {
    public SynServer(int port) {
        super(port);
    }

    // 读缓冲区
    private ByteBuffer r_bBuf = ByteBuffer.allocate(1024);
    private ByteBuffer w_bBuf;

    // 处理接收连接的事件
    @Override
    public void dealwithAccept(SelectionKey key) {
        try {
            System.out.println("新的客户端请求连接...");
            ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel sc = server.accept();
            sc.configureBlocking(false);
            // 注册读事件
            sc.register(s, SelectionKey.OP_READ);
            System.out.println("客户端连接成功...");

            // 更新最新域模型
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 处理客户端发来的消息,处理读事件
    @Override
    public void dealwithRead(SelectionKey key) {
        try {
            SocketChannel sc = (SocketChannel) key.channel();
            System.out.println("读入数据");
            r_bBuf.clear();
            // 将字节序列从此通道中读入给定的缓冲区r_bBuf
            sc.read(r_bBuf);
            r_bBuf.flip();
            String msg = Charset.forName("UTF-8").decode(r_bBuf).toString();
            if (msg.equalsIgnoreCase("time")) {
                w_bBuf = ByteBuffer.wrap(getCurrentTime().getBytes("UTF-8"));
                sc.write(w_bBuf);
                w_bBuf.clear();
            } else if (msg.equalsIgnoreCase("bye")) {
                sc.write(ByteBuffer.wrap("已经与服务器断开连接".getBytes("UTF-8")));
                sc.socket().close();
            } else {
                sc.write(ByteBuffer.wrap(msg.getBytes("UTF-8")));
            }
            System.out.println(msg);
            System.out.println("处理完毕...");
            r_bBuf.clear();
            try {
                Thread.currentThread();
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private String getCurrentTime() {
        Calendar date = Calendar.getInstance();
        String time = "服务器当前时间:" + date.get(Calendar.YEAR) + "-" + date.get(Calendar.MONTH) + 1 + "-"
                      + date.get(Calendar.DATE) + " " + date.get(Calendar.HOUR) + ":" + date.get(Calendar.MINUTE) + ":"
                      + date.get(Calendar.SECOND);
        return time;
    }
}

服务端测试类TestServer

public class TestServer {


    public static void main(String[] args) {
        Executors.newSingleThreadExecutor().submit(new SynServer(1982));
        // new Thread().start();
    }
}

 

客户端测试类TestClient

 

public class TestClient {
    public static void main(String[] args) {
        new MiniClient("localhost", 1982);
    }
}

class MiniClient {
    private SocketChannel sc;
    private ByteBuffer w_bBuf;
    private ByteBuffer r_bBuf = ByteBuffer.allocate(1024);
    
    public MiniClient(String host, int port) {
        try {
            InetSocketAddress remote = new InetSocketAddress(host, port);
            sc = SocketChannel.open();
            sc.connect(remote);
            if (sc.finishConnect()) {
                System.out.println("已经与服务器成功建立连接...");
            }
            while (true) {
                if (!sc.socket().isConnected()) {
                    System.out.println("已经与服务器失去了连接...");
                    return;
                }
                BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
                String str = br.readLine();
                System.out.println("读入一行数据,开始发送...");
                w_bBuf = ByteBuffer.wrap(str.getBytes("UTF-8"));
                // 将缓冲区中数据写入通道
                sc.write(w_bBuf);
                System.out.println("数据发送成功...");
                w_bBuf.clear();
                System.out.println("接收服务器端响应消息...");
                try {
                    Thread.currentThread();
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                r_bBuf.clear();
                // 将字节序列从此通道中读入给定的缓冲区r_bBuf
                sc.read(r_bBuf);
                r_bBuf.flip();
                String msg = Charset.forName("UTF-8").decode(r_bBuf).toString();
                System.out.println(msg);
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值