我使用NIO来接收一段消息,连接上后,将获取到的SocketChannel绑定到Selector上
监听读事件。
有读事件时,将SelectionKey提交给一个线程池中的线程异步处理
这个时候,我通过单步运行调试和添加system.out发现了一些问题,看到Selector一直select到有一个通道有读事件,一直重复执行selectionKey.isReadable() 下的内容,即Selector.select()一直返回1
初步怀疑,是不是因为系统认为我没有处理这个读事件?
system.out的部分重复内容:
接收部分代码:
public void StartServer(){ try { System.out.println("Trying to Start the Server... ..."); ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.bind(new InetSocketAddress(1234)); serverChannel.configureBlocking(false); System.out.println("Success to Start the Server... ..."); threadPoolExecutor.execute(new QueueListener(MessageQueue)); Selector selector = Selector.open(); SelectionKey key = serverChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { int select = selector.select(); if (select > 0) { Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectedKeys.iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); iterator.remove(); // 接收连接请求 if (selectionKey.isAcceptable()) { ServerSocketChannel channel = (ServerSocketChannel) selectionKey .channel(); SocketChannel socketChannel = channel.accept(); System.out.println("接收到连接请求:" + socketChannel.getRemoteAddress().toString()); socketChannel.configureBlocking(false); //每接收请求,注册到同一个selector中处理 socketChannel.register(selector, SelectionKey.OP_READ); } else if (selectionKey.isReadable()) { System.out.println("接收到读信号,开线程进行读取... ..."); threadPoolExecutor.execute(new ReciveMessageTask(selectionKey,MessageQueue)); } } } } } catch (IOException e) { System.out.println("Start Server Fail"); } }
//接受消息线程
public class ReciveMessageTask implements Runnable { private SocketChannel socketChannel; private LinkedBlockingQueue<byte[]> MessageQueue; ReciveMessageTask(SelectionKey selectionKey, LinkedBlockingQueue<byte[]> queue){ SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); this.socketChannel=socketChannel; this.MessageQueue=queue; } @Override public void run() { ByteBuffer buffer = ByteBuffer.allocate(1024); byte[] b; try { b=new byte[16]; int index=0; buffer.clear(); int cout=socketChannel.read(buffer); while(cout!=-1){ buffer.flip(); while (buffer.hasRemaining()){ byte getchar=buffer.get(); System.out.println(getchar); b[index]=getchar; index++; } buffer.clear(); cout=socketChannel.read(buffer); } System.out.println("put Message into Queue... ..."); MessageQueue.offer(b); } catch (Exception e) { try { e.printStackTrace(); //取消这个通道的注册,关闭资源 socketChannel.close(); } catch (IOException ex) { } } } }
找到原因了吗 试试在调用完异步处理后sleep几秒钟