1. 程式人生 > >nio底層如果通過selector進行c/s通訊

nio底層如果通過selector進行c/s通訊

傳統的BIO - Blocking IO - 阻塞式IO
BIO的缺點

  1. 如果有大量的請求訪問伺服器,那麼就要產生大量的執行緒去應對這些請求,導致伺服器資源過於緊張
  2. 在完成一次任務的過程中需要建立大量的輸入或者輸出流。
  3. 資料通過流傳輸,無法實現定點操作
  4. 阻塞模式
    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();
			}
		}
	}