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的功能。