使用socketchannel建立长连接,轮询server端。
发现一个问题。从3g切换到wifi时,该连接会抛Exception,catch后可以进行重新连接(会自动选择wifi),一切正常。
可是,使用wifi连接,关闭wifi切换到3g,会出现selector.select()获取到key,迭代器遍历(iterator.hasNext())却会判断为没有key。
程序卡死在两个while之间。
//出现这个格式的死循环 while (true) { code_excute... while (false) { code_not_excute } }
code:
/** * 网络上的消息和指令处理 */ private void netProcess() { Selector selector = null; SocketChannel channel = null; try { selector = Selector.open(); channel = SocketChannel.open(); //非阻塞模式 channel.configureBlocking(false); //向selector注册该通道 channel.register(selector, SelectionKey.OP_CONNECT); channel.connect(new InetSocketAddress(StatusSet.getIp(), Integer.parseInt(StatusSet.getPort_msg()))); Log.d("tag", "ip(MessageHandler): " + StatusSet.getIp()); Log.d(TAG, "连接服务器..." + new Date()); // selector.select()------Detects if any of the registered // channels is ready for I/O operations according to its interest set. boolean deadWhile = false; while(!StaticPara.isPolling_reset() && !deadWhile) { deadWhile = true; //获取channel里准备好的key selector.select(60000); Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); //迭代全部的key while(iterator.hasNext()) { deadWhile = false; SelectionKey key = iterator.next(); //一个key被处理完成后,就都被从就绪关键字(ready keys)列表中除去 iterator.remove(); // SocketChannel socketChannel = (SocketChannel)key.channel(); if(key.isConnectable()) { //true if the connection is initiated but not finished; false otherwise. // if(socketChannel.isConnectionPending()) { // socketChannel.finishConnect(); if(channel.isConnectionPending()) { channel.finishConnect(); } //重置重连的时间间隔 reconnectedInterval = Utils.interval_reset(); //图标 MyNotification.getInstance().setNotication_type(StaticPara.ZDB_NORMAL); //跳转 MyNotification.getInstance().setContentIntent_type(StaticPara.MAIN); //显示的文字 MyNotification.getInstance().setInfo(StaticPara.ZERO, 0); //运行 mNM.notify(1717,MyNotification.getInstance().getNotification()); Log.d(TAG, "connected"); key.interestOps(SelectionKey.OP_WRITE); //首先发送轮询请求 actionType = ActionType.Polling; } else if(key.isWritable()) { //查看是否在工作时间 doInWorkTime(); while (Utils.isCalling()) { /* 正在通话或者正在拨号 */ //时间间隔interval,一次轮询 Thread.sleep(INT_Para.MSG_INTERVAL); } //输出处理 writeProcess(channel, key, selector); } else if(key.isReadable()) { //读入处理 readProcess(channel, key, selector); } } //end of while(iterator.hasNext()) } //end of while(true) Log.d("stop", TAG); throw new EOFException(); } catch(Exception e) { StaticPara.setPolling_reset(false); //重连 reConn(selector, channel); } }
无奈对nio和socket研究半天没明白为什么会出现有key却不能遍历的情况,
用了其他解决方法:使用一个状态值判断有没有进入过第二个while内部。
这样的解决方法有效却不优雅,
期望有人对这个问题解惑。