在學習nio入門前,請先學習前一篇文章,理清nio三大組件的關係
圖解關係:
說明:
當客戶端連接時,會通過ServerSocketChannel
,得到SocketChannel將socketChannel註冊到Selector上,並且返回一個
selectorKey,該SelectorKey會和Selector關聯selector進行監聽select方法,返回有事件發生的通道個數
進一步得到各個SelectKey
再通過SelectKey,反向獲取channel
最後通過channel完成對應的事件
服務端:
public static void main(String[] args) throws IOException {
//創建serverSocketChannel
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//創建selector對象
Selector selector = Selector.open();
//綁定端口6666,在服務器端監聽
serverSocketChannel.socket().bind(new InetSocketAddress(6666));
//設置非阻塞
serverSocketChannel.configureBlocking(false);
//把ServerSocketChannel註冊到Selector
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
//循環等待客戶端請求
while (true) {
if (selector.select(1000) == 0) {
System.out.println("服務器等待了1秒,無連接");
continue;
}
//獲取selectorKey集合
Set<SelectionKey> selectionKeys = selector.selectedKeys();
//遍歷集合
for (SelectionKey key : selectionKeys) {
//反向獲取到channel,根據不同事件做出處理
if (key.isAcceptable()) {//如果是連接請求
//給該客戶端生成一個socketChannel
SocketChannel channel = serverSocketChannel.accept();
//將當前的channel註冊到selector上
channel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
}
if (key.isReadable()) {//讀的請求
//獲取到該channel
SocketChannel channel = (SocketChannel) key.channel();
//獲取buffer
ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
channel.read(byteBuffer);
System.out.println("from 客戶端" + new String(byteBuffer.array()));
}
//最後移出
selectionKeys.remove(key);
}
}
}
客戶端:
public static void main(String[] args) throws IOException {
SocketChannel socketChannel=SocketChannel.open();
//非阻塞
socketChannel.configureBlocking(false);
//提供服務端的ip和端口
InetSocketAddress address=new InetSocketAddress("127.0.0.1",6666);
//連接服務器
if(!socketChannel.connect(address)){
while(!socketChannel.finishConnect()){
System.out.println("因爲連接需要事件,可以做其他的事情");
}
}else {
//連接成功了
String str="hello world";
ByteBuffer byteBuffer=ByteBuffer.wrap(str.getBytes());
//將數據寫入channel
socketChannel.write(byteBuffer);
}
}