處理可寫事件
什么情況下需要注冊可寫事件?
- 在服務(wù)端一次性無法把數(shù)據(jù)發(fā)送完的情況下,需要注冊可寫事件
- 服務(wù)端一次性是否能夠把數(shù)據(jù)全部發(fā)送完成取決于服務(wù)端的緩沖區(qū)大小,該緩沖區(qū)不受程序控制
注冊可寫事件的步驟
-
判斷ByteBuffer是否仍有剩余,如果有剩余注冊可寫事件
ByteBuffer bf = "hello client,welcome"; SocketChannel sc = (SocketChannel) selectionKey.channel(); sc.write(bf); if(bf.hasRemaining){ selectionKey.interestOps(SelectionKey.OP_READ + SelectionKey.OP_WRITE); selectionKey.attachment(bf); }
-
監(jiān)聽可寫事件,判斷數(shù)據(jù)是否寫完,數(shù)據(jù)寫完需要
if (key.isWritable()){ // 監(jiān)聽可寫事件 SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer byteBuffer = (ByteBuffer) key.attachment(); channel.write(byteBuffer); if (!byteBuffer.hasRemaining()) { // 判斷數(shù)據(jù)是否寫完 // 數(shù)據(jù)寫完,解除對buffer的引用 key.attach(null); // 數(shù)據(jù)寫完,不再關(guān)注可寫事件 key.interestOps(key.interestOps() - SelectionKey.OP_WRITE); } }
代碼示例
-
客戶端文章來源:http://www.zghlxwxcb.cn/news/detail-673294.html
package com.ysf; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; public class Client { public static void main(String[] args) throws IOException { SocketChannel sc = SocketChannel.open(); sc.connect(new InetSocketAddress("127.0.0.1",11027)); sc.write(Charset.defaultCharset().encode("123456\n223456\nhello server\n")); while (true){ ByteBuffer allocate = ByteBuffer.allocate(16); sc.read(allocate); allocate.flip(); System.out.println(Charset.defaultCharset().decode(allocate)); } } }
-
服務(wù)端文章來源地址http://www.zghlxwxcb.cn/news/detail-673294.html
package com.ysf; import java.io.IOException; import java.net.InetSocketAddress; 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.HashMap; import java.util.Iterator; import java.util.Map; public class WriterSelectorServer { public static void handleContent(ByteBuffer byteBuffer){ byteBuffer.flip(); for (int i = 0;i < byteBuffer.limit();i++){ if (byteBuffer.get(i) == '\n'){ int length = i + 1 - byteBuffer.position(); ByteBuffer allocate = ByteBuffer.allocate(length); for (int j = 0;j<length;j++){ allocate.put(byteBuffer.get()); } allocate.flip(); System.out.println(Charset.defaultCharset().decode(allocate)); } } byteBuffer.compact(); } public static void main(String[] args) throws IOException { Selector selector = Selector.open(); ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.configureBlocking(false); ssc.bind(new InetSocketAddress(11027)); SelectionKey sscKey = ssc.register(selector, 0, null); sscKey.interestOps(SelectionKey.OP_ACCEPT); while (true){ selector.select(); Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()){ SelectionKey key = iterator.next(); iterator.remove(); if (key.isAcceptable()){ ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel(); SocketChannel sc = serverSocketChannel.accept(); sc.configureBlocking(false); ByteBuffer welcome = Charset.defaultCharset().encode("welcome"); sc.write(welcome); Map<String,ByteBuffer> attach = new HashMap<>(); ByteBuffer readBuffer = ByteBuffer.allocate(16); attach.put("read",readBuffer); SelectionKey scKey = sc.register(selector, 0, attach); if (welcome.hasRemaining()){ attach.put("write",welcome); scKey.interestOps(SelectionKey.OP_READ + SelectionKey.OP_WRITE); }else { scKey.interestOps(SelectionKey.OP_READ); } }else if (key.isReadable()){ SocketChannel channel = (SocketChannel) key.channel(); Map<String, ByteBuffer> attachment = ((Map<String,ByteBuffer>) key.attachment()); ByteBuffer readBuffer = attachment.get("read"); int read; try { read = channel.read(readBuffer); } catch (IOException e) { e.printStackTrace(); key.cancel(); continue; } if (read == -1){ key.cancel(); }else { handleContent(readBuffer); if (readBuffer.position() == readBuffer.limit()){ ByteBuffer newAttachment = ByteBuffer.allocate(readBuffer.capacity() * 2); readBuffer.flip(); newAttachment.put(readBuffer); attachment.put("read",newAttachment); } } }else if (key.isWritable()){ SocketChannel channel = (SocketChannel) key.channel(); Map<String, ByteBuffer> attachment = (Map<String, ByteBuffer>) key.attachment(); ByteBuffer byteBuffer = attachment.get("write"); channel.write(byteBuffer); if (!byteBuffer.hasRemaining()) { attachment.remove("write"); key.interestOps(key.interestOps() - SelectionKey.OP_WRITE); } } } } } }
到了這里,關(guān)于netty(二):NIO——處理可寫事件的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!