nio底層如果通過selector進行c/s通訊
阿新 • • 發佈:2018-11-10
傳統的BIO - Blocking IO - 阻塞式IO
BIO的缺點
- 如果有大量的請求訪問伺服器,那麼就要產生大量的執行緒去應對這些請求,導致伺服器資源過於緊張
- 在完成一次任務的過程中需要建立大量的輸入或者輸出流。
- 資料通過流傳輸,無法實現定點操作
- 阻塞模式
NIO - New IO - 非阻塞式IO:Buffer,Channel,Selector — Buffer是容器,用於儲存資料;Channel用於傳輸;Selector進行過濾。
Buffer - 緩衝區
用於進行資料的儲存。操作的都是基本型別。
資料在操作的時候是根據操作位的位置決定。
限制位是決定操作位所能達到的最大下標
標記位<= 操作位<= 限制位<= 容量位
Channel - 通道
傳輸資料,基於緩衝區進行傳輸。可以進行雙向傳輸。
Selector - 多路複用通道選擇器
底層如果通過selector進行c/s通訊的程式碼實現
ClientSelector類
public static void main(String[] args) throws IOException { SocketChannel sc=SocketChannel.open(); sc.configureBlocking(false); sc.connect(new InetSocketAddress("localhost", 8090)); Selector selc=Selector.open(); sc.register(selc, SelectionKey.OP_CONNECT); while(true){ selc.select(); Set <SelectionKey> keys=selc.selectedKeys(); Iterator<SelectionKey> it=keys.iterator(); while(it.hasNext()){ SelectionKey key=it.next(); if(key.isConnectable()){ SocketChannel scx=(SocketChannel) key.channel(); while(!scx.finishConnect()); scx.register(selc, SelectionKey.OP_READ|SelectionKey.OP_WRITE); } if(key.isReadable()){ SocketChannel scx=(SocketChannel) key.channel(); ByteBuffer buffer=ByteBuffer.allocate(1024); scx.read(buffer); System.out.println(new String(buffer.array(),0,buffer.position())); sc.register(selc, key.interestOps()^SelectionKey.OP_READ); } if(key.isWritable()){ SocketChannel scx=(SocketChannel) key.channel(); scx.write(ByteBuffer.wrap("你好伺服器".getBytes())); sc.register(selc,key.interestOps()^SelectionKey.OP_WRITE); } it.remove(); } } }
ServerSelector類
public static void main(String[] args) throws IOException { ServerSocketChannel ssc=ServerSocketChannel.open(); ssc.bind(new InetSocketAddress(8090)); ssc.configureBlocking(false); Selector selc=Selector.open(); ssc.register(selc, SelectionKey.OP_ACCEPT); while(true){ selc.select(); Set <SelectionKey> keys=selc.selectedKeys(); Iterator<SelectionKey> it=keys.iterator(); while (it.hasNext()) { SelectionKey key = it.next(); if(key.isAcceptable()){ ServerSocketChannel sscx=(ServerSocketChannel) key.channel(); SocketChannel sc=sscx.accept(); while(sc==null) sc=sscx.accept(); sc.configureBlocking(false); sc.register(selc, SelectionKey.OP_READ| SelectionKey.OP_WRITE); } if(key.isReadable()){ SocketChannel sc=(SocketChannel) key.channel(); ByteBuffer buffer=ByteBuffer.allocate(1024); sc.read(buffer); System.out.println(new String(buffer.array(),0,buffer.position())); sc.register(selc,key.interestOps()^SelectionKey.OP_READ); } if(key.isWritable()){ SocketChannel sc=(SocketChannel) key.channel(); sc.write(ByteBuffer.wrap("你好客戶端".getBytes())); sc.register(selc, key.interestOps()^SelectionKey.OP_WRITE); } it.remove(); } } }