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 }