`
v5browser
  • 浏览: 1138630 次
社区版块
存档分类
最新评论

android使用SocketChannel,关闭wifi切换到3g时出现死循环

 
阅读更多

使用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内部。

这样的解决方法有效却不优雅,

期望有人对这个问题解惑。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics