使用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内部。
这样的解决方法有效却不优雅,
期望有人对这个问题解惑。