java selector使用select輪詢注冊到selector中的channel,如果有channel准備好注冊的事件,select()返回,返回值為可以操作的channel的個數。通過selector.selectedKeys()返回選中的key的集合。遍歷集合中所有的key,判斷key的事件,進行相應的處理,並從集合中remove掉。
客戶端selector的使用邏輯與服務端selector使用邏輯幾乎一致。
Server代碼中監聽了兩個端口8888和8889兩個端口,並注冊到selector中。讀取客戶端發送的信息,並發送信息到客戶端
Client代碼向服務器對應的端口號發送信息,並接收服務器端返回的信息
這里我服務端用了channel+selector客戶端直接用的socket,可以發送給服務端信息,但接收服務端信息沒有接收到(代碼沒有貼出來)
PS:使用selector+channel可以在一個線程內監聽多個channel,下面代碼中就監聽了兩個端口的channel
SelectorServer.java
1 import java.io.IOException; 2 import java.net.InetSocketAddress; 3 import java.net.ServerSocket; 4 import java.nio.ByteBuffer; 5 import java.nio.channels.SelectionKey; 6 import java.nio.channels.Selector; 7 import java.nio.channels.ServerSocketChannel; 8 import java.nio.channels.SocketChannel; 9 import java.util.Iterator; 10 import java.util.Set; 11 12 /** 13 * Created by 58 on 2016/11/28. 14 */ 15 public class SelectorServer { 16 public static void main(String args[]){ 17 startServer(); 18 } 19 public static ByteBuffer sendBuffer = ByteBuffer.allocate(1024); 20 public static ByteBuffer receiveBuffer = ByteBuffer.allocate(1024); 21 22 public static void startServer(){ 23 //用兩個channel監聽兩個端口 24 int listenPort = 8888; 25 int listenPort1 = 8889; 26 sendBuffer.put("message from server".getBytes()); 27 28 try { 29 //創建serverchannel,綁定對應的端口 30 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); 31 ServerSocket serverSocket = serverSocketChannel.socket(); 32 InetSocketAddress inetSocketAddress = new InetSocketAddress(listenPort); 33 serverSocket.bind(inetSocketAddress); 34 35 //創建第二個channel 36 ServerSocketChannel serverSocketChannel1 = ServerSocketChannel.open(); 37 ServerSocket serverSocket1 = serverSocketChannel1.socket(); 38 InetSocketAddress inetSocketAddress1 = new InetSocketAddress(listenPort1); 39 serverSocket1.bind(inetSocketAddress1); 40 41 42 //創建selector對象 43 Selector selector = Selector.open(); 44 45 //設置channel注冊到selector中 46 serverSocketChannel.configureBlocking(false); 47 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); 48 49 //第二個channel 50 serverSocketChannel1.configureBlocking(false); 51 serverSocketChannel1.register(selector, SelectionKey.OP_ACCEPT); 52 53 System.out.println("start to listen port: " + listenPort); 54 System.out.println("start to listen port: " + listenPort1); 55 56 //監聽端口 57 while(true){ 58 int readyChannels = selector.select(); 59 if(readyChannels == 0) 60 continue; 61 Set<SelectionKey> selectedKeys = selector.selectedKeys(); 62 Iterator<SelectionKey> iterator = selectedKeys.iterator(); 63 while(iterator.hasNext()){ 64 SelectionKey selectionKey = iterator.next(); 65 dealSelectionKey(selector, selectionKey); 66 67 iterator.remove(); 68 }//while 69 }//while 70 71 72 } catch (IOException e) { 73 e.printStackTrace(); 74 } 75 } 76 77 public static void dealSelectionKey(Selector selector, SelectionKey selectionKey){ 78 try{ 79 //准備好接收新的連接 80 if(selectionKey.isAcceptable()){ 81 ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel(); 82 SocketChannel clientSocketChannel = serverSocketChannel.accept(); 83 clientSocketChannel.configureBlocking(false); 84 clientSocketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); 85 System.out.println("channel is ready acceptable"); 86 } 87 else if(selectionKey.isConnectable()){ 88 selectionKey.channel().register(selector, SelectionKey.OP_READ); 89 System.out.println("channel is connectable."); 90 } 91 else if(selectionKey.isReadable()){ 92 //讀去客戶端內容 93 SocketChannel clientSocketChannel = (SocketChannel) selectionKey.channel(); 94 receiveBuffer.clear(); 95 clientSocketChannel.read(receiveBuffer); 96 selectionKey.interestOps(SelectionKey.OP_WRITE); 97 System.out.println("message from client is: " + new String(receiveBuffer.array())); 98 System.out.println("Thread id : " + Thread.currentThread().getId()); 99 } 100 else if(selectionKey.isWritable()){ 101 //向客戶端寫數據 102 SocketChannel clientSocketChannel = (SocketChannel) selectionKey.channel(); 103 sendBuffer.flip(); 104 System.out.println("sendBuffer = " + new String(sendBuffer.array())); 105 clientSocketChannel.write(sendBuffer); 106 selectionKey.interestOps(SelectionKey.OP_READ); 107 System.out.println("channle is writable."); 108 }//else if 109 }catch (Exception e){ 110 111 } 112 } 113 }
SelectorClient.java
1 import java.io.IOException; 2 import java.net.InetSocketAddress; 3 import java.nio.ByteBuffer; 4 import java.nio.channels.SelectionKey; 5 import java.nio.channels.Selector; 6 import java.nio.channels.SocketChannel; 7 import java.util.Iterator; 8 import java.util.Set; 9 10 /** 11 * Created by 58 on 2016/11/28. 12 */ 13 public class SelectorClient { 14 public static void main(String args[]){ 15 work(); 16 } 17 18 public static void work(){ 19 int serverPort = 8888; 20 ByteBuffer sendBuffer = ByteBuffer.wrap("client message".getBytes()); 21 ByteBuffer receiveBuffer = ByteBuffer.allocate(1024); 22 try { 23 //創建通道,設置通道注冊到selector中 24 SocketChannel socketChannel = SocketChannel.open(); 25 Selector selector = Selector.open(); 26 27 socketChannel.configureBlocking(false); 28 socketChannel.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ | SelectionKey.OP_CONNECT); 29 socketChannel.connect(new InetSocketAddress("localhost", serverPort)); 30 int executeTimes = 2; 31 //while 32 while(executeTimes > 0){ 33 executeTimes--; 34 int reayChannelNum = selector.select(); 35 if(reayChannelNum == 0){ 36 continue; 37 } 38 Set<SelectionKey> setOfSelectionKey = selector.selectedKeys(); 39 Iterator<SelectionKey> iterator = setOfSelectionKey.iterator(); 40 while(iterator.hasNext()){ 41 SelectionKey selectionKey = iterator.next(); 42 SocketChannel socketChannel1 = (SocketChannel) selectionKey.channel(); 43 iterator.remove(); 44 if(selectionKey.isConnectable()){ 45 if(socketChannel1.isConnectionPending()){ 46 socketChannel1.finishConnect(); 47 System.out.println("connection complete."); 48 socketChannel1.write(sendBuffer); 49 } 50 }//if isConnectable 51 else if(selectionKey.isReadable()){ 52 receiveBuffer.clear(); 53 socketChannel1.read(receiveBuffer); 54 receiveBuffer.flip(); 55 System.out.println("message from server: " + new String(receiveBuffer.array())); 56 57 }//else if readable 58 else if(selectionKey.isWritable()){ 59 sendBuffer.flip(); 60 socketChannel1.write(sendBuffer); 61 } 62 } 63 } 64 } catch (IOException e) { 65 e.printStackTrace(); 66 } 67 } 68 }