使用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内部。
这样的解决方法有效却不优雅,
期望有人对这个问题解惑。
分享到:
相关推荐
java的ServerSocketChannel与SocketChannel的使用
SocketChannel非阻塞网络编程
一个关于SocketChannel、ServerSocketChannel、Selector的综合案例
这是一个非阻塞通信学习的基础模板,让你轻松掌握非阻塞通信。里面还包含了可运行的jar包,可以抢先体验效果哦~_~
代理套接字通道 一个 Java SocketChannel 实现,它使用提供的 Proxy 实例通过提供的代理建立... 请注意,这是 SocketChannel 实例的默认行为,因此除非项目显式切换到非阻塞模式,否则此实现可能已经足以满足您的目的。
使用Maven 将以下依赖项添加到您的Maven项目中: < dependency> < groupId>org.baswell</ groupId> < artifactId>niossl</ artifactId> < version>0.2</ version></ dependency>复制来源该项目只是几个源文件,没有...
NIO(服务端和客户端代码) 博文链接:https://songjianyong.iteye.com/blog/1757406
使用socket channel 连接服务器,断线重连,发送保活等的封装类。 Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。可以通过以下2种方式创建SocketChannel: 打开一个SocketChannel并连接到互联网上的...
使用WiFi Direct进行对等通信的聊天应用此应用程序使用WiFi Direct P2P频道来交换...Google Android Analytic Event跟踪要使用Google Analytics(分析),您所需要做的就是将libGoogleAnalytics.jar粘贴到项目的libs
没有使用其他jar包 主要功能: 1、广场群聊,即发送的消息所有在线的人都能看到 2、聊天室群聊,可以创建聊天室,进入聊天室的人可以在里面聊天,创建的人或者是第一个人为管理员,拥有踢人的权限;广场上有一个...
本文实例讲述了Android在JNI中使用ByteBuffer的方法。分享给大家供大家参考。具体如下: 一、ByteBuffer 定义 在NIO中,数据的读写操作始终是与缓冲区相关联的(读取时信道(SocketChannel)将数据读入缓冲区,写入时...
【IT十八掌徐培成】Java基础第27天-02.NIO-ServerSocketChannel-SocketChannel.zip
1.客户端连接服务端,服务端通过Selector接收到连接请求,将其socketChannel通道保存到通道集合,并触发客户端连接事件 2.客户端发送数据包请求到服务端,服务端将请求的SelectionKey压入“读消息生产者队列”,立即...
利用Socket实现聊天室实时聊天功能,包含服务器端以及客户端,输入指定IP和端口号进行监控
SocketChannel被Selector检查,检查其声称可以接受的状态是否已经产生,如当SocketChannel在向Selector注册是设置了可接受状态为Read,此时当SocketChannel接收到数据后将进入可读状态。 如果需要实现一个线程或...
用JAVA写的一个FPT小程序,可实现简单的Ftp功能,Server端有Ui界面。
我们接着做别的事情,当有事件发生时,他会通知我们,传回一组SelectionKey,我们读取这些Key,就会获得我们刚刚注册过的socketchannel,然后,我们从这个Channel中读取数据,放心,包准能够读到,接着我们可以处理这些...
● SocketChannel:Socket的替代类,支持阻塞通信与非阻塞通信。 ● Selector:为ServerSocketChannel监控接收连接就绪事件,为SocketChannel监控连接就绪、读就绪和写就绪事件。 ● SelectionKey:代表...
1.ServerSocketChannel与SocketChannel通讯 2.java Fork/Join 与ThreadPool使用
客户端使用 AsynchronousSocketChannel 和 CompletableFuture 的简单 TCP 客户端