美文网首页技术栈
2019-05-11——Java NIO Socket

2019-05-11——Java NIO Socket

作者: 烟雨乱平生 | 来源:发表于2019-05-13 11:38 被阅读0次

NIO的出现使得传统的Socket的通讯发生了巨大的改变。

NIO本质就是避免原始的TCP建立连接使用的3次握手的操作,减少网络开销。

NIO是非阻塞的

相比于传统的阻塞型IO,NIO是非阻塞的,所以对于服务端有如下做法:

/*使用NIO非阻塞处理socket请求*/
public static void s5() throws IOException {
    ExecutorService threadPool = new ThreadPoolExecutor(10,50,60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.configureBlocking(false);
    serverSocketChannel.bind(new InetSocketAddress(9999));
    while (true){
        System.out.println("等待客户端接入...");
        SocketChannel socketChannel = serverSocketChannel.accept();
        if(socketChannel==null){
            continue;
        }
        threadPool.execute(()->{
            try {
                clientJoin();
                read(socketChannel);
                socketChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
    }
}

private static void read(SocketChannel socketChannel) throws IOException {
    StringBuilder content = new StringBuilder();
    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    while(socketChannel.read(byteBuffer)!=-1){
        byteBuffer.flip();
        while (byteBuffer.hasRemaining()){
            byte[] data = new byte[byteBuffer.remaining()];
            byteBuffer.get(data);
            content.append(new String(data,0,data.length));
        }
        byteBuffer.clear();
    }
    System.out.println(content.toString());
}

当然也可以使用著名的Reactoer模式

服务端

/*Reactor模型*/
public static void s6() throws IOException {
    Selector selector = Selector.open();
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.configureBlocking(false);
    serverSocketChannel.bind(new InetSocketAddress(9999));
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    while (selector.select()>0){
        Set<SelectionKey> selectionKeys = selector.selectedKeys();
        Iterator<SelectionKey> iterator = selectionKeys.iterator();
        while (iterator.hasNext()){
            SelectionKey selectionKey = iterator.next();
            if (selectionKey.isConnectable()){
                onConnection(selectionKey);
            }else if(selectionKey.isAcceptable()){
                onAccept(selectionKey);
            }else if(selectionKey.isReadable()){
                onRead(selectionKey);
            }else if(selectionKey.isWritable()){
                onWrite(selectionKey);
            }
            iterator.remove();
        }
    }
}

private static void onWrite(SelectionKey selectionKey) throws IOException {
    System.out.println("写就绪");
    SocketChannel channel = (SocketChannel) selectionKey.channel();
    write(channel);
    channel.close();
}

private static void onRead(SelectionKey selectionKey) throws IOException {
    System.out.println("读就绪");
    SocketChannel channel = (SocketChannel) selectionKey.channel();
    read(channel);
    channel.register(selectionKey.selector(),SelectionKey.OP_WRITE);
}

private static void onAccept(SelectionKey selectionKey) throws IOException {
    System.out.println("接收数据就绪");
    ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
    SocketChannel socketChannel = serverSocketChannel.accept();
    Selector selector = selectionKey.selector();
    socketChannel.configureBlocking(false);
    socketChannel.register(selector,SelectionKey.OP_READ);
}

private static void onConnection(SelectionKey selectionKey) {
    System.out.println("链接就绪");
}

private static void read(SocketChannel socketChannel) throws IOException {
    StringBuilder content = new StringBuilder();
    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    while(socketChannel.read(byteBuffer)!=-1){
        byteBuffer.flip();
        while (byteBuffer.hasRemaining()){
            byte[] data = new byte[byteBuffer.remaining()];
            byteBuffer.get(data);
            content.append(new String(data,0,data.length));
        }
        byteBuffer.clear();
    }
    System.out.println(content.toString());
}

private static void write(SocketChannel socketChannel) throws IOException {
    byte[] data = "这是服务端,正在使用Channel".getBytes();
    ByteBuffer byteBuffer = ByteBuffer.allocate(data.length);
    byteBuffer.put(data);
    byteBuffer.flip();
    socketChannel.write(byteBuffer);
}

相关文章

  • 2019-05-11——Java NIO Socket

    NIO的出现使得传统的Socket的通讯发生了巨大的改变。 NIO本质就是避免原始的TCP建立连接使用的3次握手的...

  • Java NIO

    # Java NIO # Java NIO属于非阻塞IO,这是与传统IO最本质的区别。传统IO包括socket和文...

  • grpc线程模型

    BIO 线程模型 在 JDK 1.4 推出 Java NIO 之前,基于 Java 的所有 Socket 通信都采...

  • JAVA NIO 翻译系列(八、 SocketChannel)

    Java NIO SocketChannel是一个连接tcp 协议的socket的channel。跟以前的java...

  • Socket 编程之 NIO

    本文介绍基于 NIO 实现 Socket 编程的方法及问题。 目录 NIO 简介 NIO Socket 代码示例 ...

  • Java NIO 教程(八) SocketChannel

    参考:http://ifeve.com/socket-channel/原文地址 目录 Java NIO教程 Jav...

  • Java NIO学习笔记 - BIO编程

    Java I/O演进 在JDK1.4推出Java NIO之前,基于Java的所有Socket通信都采用了同步阻塞模...

  • Java NIO socket通信

    Java NIO 是Java1.4版本推出的新的IO接口,全称Java Non-BlockingIO,也有人称之为...

  • 关于TCP 半连接队列和全连接队列

    问题描述 JAVA的client和server,使用socket通信。server使用NIO。 1.间歇性的出现c...

  • nio

    参考文章 Java Nio Java NIO学习笔记 - NIO客户端时序图 Java NIO学习笔记 - NIO...

网友评论

    本文标题:2019-05-11——Java NIO Socket

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