`
yznxing
  • 浏览: 367153 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

java学习——NIO篇

    博客分类:
  • java
阅读更多

Nio也就是继JDK1.4之后关于io的新特性的new Io,也就是传说中的无阻塞io。

Nio主要包括几个方面:
ByteBuffer:Channel:Selector:
原理部分下次再整理,本次主要是进行实例。
下面要实现就是使用nio进行简单的文本传递。

服务端:

public class MainServer {
    private static final int port = 19999;
    private static ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        ServerSocketChannel server = ServerSocketChannel.open();
        Selector sel = Selector.open();
        server.socket().bind(new InetSocketAddress(port));
        //无阻塞
        server.configureBlocking(false);
        //绑定连接事件。
        server.register(sel, SelectionKey.OP_ACCEPT);
        System.out.println("server start");
        while (true) {
            sel.select();
            Iterator iter = sel.selectedKeys().iterator();
            while (iter.hasNext()) {
                SelectionKey key = (SelectionKey) iter.next();
                iter.remove();
                // 判断是否有新的连接到达
                if (key.isAcceptable()) {
                    System.out.println("有新连接");
                    SocketChannel sc = server.accept();
                    sc.configureBlocking(false);
                    sc.register(sel, SelectionKey.OP_READ);
                }
                //判断是否可读取
                if (key.isReadable()) {
                    SocketChannel sc = (SocketChannel) key.channel();
                    sc.configureBlocking(false);
                    int count = sc.read(buffer);
                    if (count <= 0) {
                        System.out.println("客户端已经关闭了");
                        sc.close();
                    } else {
                        System.out.println("有数据过来了");
                        buffer.flip();
                        byte[] bytes = new byte[buffer.remaining()];
                        buffer.get(bytes);
                        String msg = new String(bytes);
                        System.out.println("收到信息>>" + msg);
                        buffer.clear();
                    }

                }
            }
        }
    }
}
 

客户端:

public class MainClient {

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        SocketChannel client = SocketChannel.open();
        client.configureBlocking(false);
        Selector selector = Selector.open();
        client.register(selector, SelectionKey.OP_CONNECT);
        client.connect(new InetSocketAddress("localhost", 19999));

        String message = "client test";
        ByteBuffer bb = ByteBuffer.allocate(message.length());
        boolean flag = true;

        while (flag) {
            selector.select();
            Iterator it = selector.selectedKeys().iterator();
            while (it.hasNext()) {
                SelectionKey key = (SelectionKey) it.next();
                it.remove();
                if (key.isConnectable()) {
                    System.out.println("客户端连接上");
                    SocketChannel sc = (SocketChannel) key.channel();
                    if (sc.isConnectionPending())
                        sc.finishConnect();
                    sc.register(selector, SelectionKey.OP_WRITE);
                }
                if (key.isWritable()) {
                    System.out.println("客户端可以写");
                    SocketChannel sc = (SocketChannel) key.channel();
                    bb.clear();
                    bb.put(message.getBytes());
                    bb.flip();
                    sc.write(bb);
                    //发完一条信息,退出发送,关闭连接。
                    flag = false;
                }
            }
        }
        //关闭连接
        client.close();
    }
}
 

心得:
使用NIO进行传输的时候,也跟普通scoket差不多。其中使用ServerSocketChannel来作为服务端的channel,使用SocketChannel作为客户端的channel。其中channel可以理解为连接的通道。
sel.select();
Iterator iter = sel.selectedKeys().iterator();
chanel的selectedKeys可以理解为一次连接的实例了。每一个key可以调用其channel方法生成一个ScoketChannel。然后通过这个ScoketChannel来获取传输的内容,或者输入内容。

PS:
在服务端获取客户端传输过来的字符串时,使用ByteBuffer获得的方法是:
buffer.flip();
byte[] bytes=new byte[buffer.remaining()];
buffer.get(bytes);
String msg = new String(bytes);
通过该方法可以将客户端传送的字符byte组装为String。

在客户端传输的为一个固定的String,也可以将这个demo改写,改成控制台输入,作成一个简单的聊天程序。

另外,注意buffer.flip() 的运用。


0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics