NIO(非阻塞IO)實現通信

import java.net.InetSocketAddress;
import java.net.SocketAddress;
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 class NIOServerSocket {
    public static void main(String[] args) throws Exception{
        //開啓服務端的通道
        ServerSocketChannel channel = ServerSocketChannel.open();
        //設置socket是非阻塞的 阻塞模式是爲了兼容BIO
        channel.configureBlocking(false);
        //綁定7711端口
        channel.bind(new InetSocketAddress(7711) );
        //開啓選擇器
        Selector selector = Selector.open();
        //注冊事件
        channel.register(selector, SelectionKey.OP_ACCEPT);
        while (true){
            //選擇方法是阻塞的
            int count = selector.select();
            if(count <= 0) continue;
            //關注點的集合
            Set<SelectionKey> keys =  selector.selectedKeys();
            //迭代
            Iterator<SelectionKey> iterator = keys.iterator();
            while(iterator.hasNext()){
                SelectionKey key = iterator.next();
                //accept被激活説明有客戶端連接
                if(key.isAcceptable()){
                    SocketChannel clientSocket = channel.accept();
                    //設置非阻塞模式
                    clientSocket.configureBlocking(false);
                    //注冊讀事件
                    clientSocket.register(selector,SelectionKey.OP_READ);
                    SocketAddress address = clientSocket.getRemoteAddress();
                    String address1 =  address.toString();
                    System.out.println("有客戶端連接 " + address1+ ":為客戶端注冊可讀事件");
                }
                else if(key.isReadable()){
                    //讀數據
                    SocketChannel socketChannel =  (SocketChannel)key.channel();
                    //設置緩衝區大小
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    //讀取緩衝區的數據
                    socketChannel.read(buffer);
                    //channel進入讀取模式
                    buffer.flip();
                    //獲取讀到的信息
                    String receive =  Charset.forName("utf-8").newDecoder().decode(buffer).toString();
                    System.out.println("服務端收到 :" +  receive );
                    buffer.clear();
                    buffer =  buffer.put(("receiveString : " + receive ).getBytes("utf-8"));
                    //回到讀取模式
                    buffer.flip();
                    //將數據囘寫給客戶端
                    socketChannel.write(buffer);
                    //注冊事件為讀取
                    socketChannel.register(selector,SelectionKey.OP_READ);
                }
                //處理完后移除這個注冊
                iterator.remove();
            }
        }
    }
}
使用telnet作爲客戶端,發現nio在主綫程中可以處理多個客戶端請求,而不需要啓動多個綫程

這裏簡單介紹下Netty

引用官網的原話,Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。

實際上Netty是對Java中NIO的封裝,下片本博文我會模擬實現Netty的功能。

猜你喜欢

转载自blog.csdn.net/Bai_xing_yu/article/details/88795448
今日推荐