Mina框架 open to many file 错误原因以及解决方案
来源:互联网 发布:c语言需要掌握 编辑:程序博客网 时间:2024/06/05 06:14
前几天用Mina2.0创建了一个tcp c/s架构的程序,可以实现客户端与服务器的长连接,方便向客户端反向推送一些消息。
项目的演示地址在:http://182.254.136.237:8080/RoomControllerServerCore/management/list.jsp
经过一天晚上的压力测试,服务器端表现非常的完美,客户端的上线,正常下线与不正常下线都能立即检测的到,踢掉客户端功能也运行正常。问题就在于我的Pad端,Android5.1系统,x86架构,昂达的Pad,出现了问题。一夜之后wifi就无法连接了,用adb勉强连上Pad logcat一下发现system_process进程一直在尝试重新连接已经保存的无线,可是最终都会报出一个错误:无法得到文件描述符。于是我使用adb shell 连进Adnroid内核shell,lsof一下,发现打印出来的列表n多,当时我的内心是崩溃的,不过心里也有点小高兴,因为我找到了问题的所在,有可能= =。。
问题出在我的代码上。
修改之前的代码:
package core;import java.net.InetSocketAddress;import org.apache.mina.core.future.ConnectFuture;import org.apache.mina.core.service.IoConnector;import org.apache.mina.core.service.IoHandler;import org.apache.mina.core.service.IoHandlerAdapter;import org.apache.mina.core.session.IdleStatus;import org.apache.mina.core.session.IoSession;import org.apache.mina.filter.codec.ProtocolCodecFilter;import org.apache.mina.filter.keepalive.KeepAliveFilter;import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;import org.apache.mina.transport.socket.nio.NioSocketConnector;import base.Global;public class TcpClient extends Thread{private final static boolean DEBUG = true;private IoConnector conn = null;private IoSession session = null;private IoHandler handler = null;private ClientStatus clientStatus = ClientStatus.IDLE;private InetSocketAddress inetAddress = null;public TcpClient() {// init minaconn = new NioSocketConnector();conn.setConnectTimeoutMillis(1000 * 60); conn.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MessageCodecFactory()));/** 主角登场 */ KeepAliveMessageFactory heartBeatFactory = new KeepAliveMessageFactoryImpl(); KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory, IdleStatus.BOTH_IDLE); /** 是否回发 */ heartBeat.setForwardEvent(true); /** 发送频率 */ heartBeat.setRequestInterval(15); // connector.getSessionConfig().setKeepAlive(true); conn.getFilterChain().addLast("heartbeat", heartBeat); if(null == handler) {handler = new DefaultClientHandler();}conn.setHandler(handler); start();}public IoSession getSession() {return session;}@Overridepublic void run() {for(;;) {try {switch (clientStatus) {case IDLE:break;case RUNNING:if(DEBUG) {System.out.println("Connecting...");}// conn = new NioSocketConnector(); ConnectFuture future = conn.connect(inetAddress);// �������� future.awaitUninterruptibly();// �ȴ����Ӵ������ session = future.getSession();// ���session Global.cr.onSessionOk(session);if(DEBUG) {System.out.println("Connected !");}session.getCloseFuture().awaitUninterruptibly();// �ȴ����ӶϿ� if(DEBUG) {System.out.println("Disconnected ~");}session.close(false);// conn.dispose(); break;case QUIT:return ;default:break;}}catch(Exception e) {e.printStackTrace();continue ;} finally {try {Thread.sleep(1000 * 1);} catch (InterruptedException e) {e.printStackTrace();}}}}/** * * @param inetAddress * @return */public boolean connect(InetSocketAddress inetAddress, IoHandler handler) {this.inetAddress = inetAddress;this.handler = handler;conn.setHandler(handler);if(clientStatus == ClientStatus.RUNNING) {return false;} else if(clientStatus == ClientStatus.IDLE) {clientStatus = ClientStatus.RUNNING;return true;} else if(clientStatus == ClientStatus.QUIT) {return false;}return true;}@SuppressWarnings("deprecation")public boolean disconnect() {if(clientStatus == ClientStatus.RUNNING) {clientStatus = ClientStatus.IDLE;session.close();return true;}return false;}public boolean send(String msg) {if(null != session && session.isConnected())session.write(msg);return true;}public static class DefaultClientHandler extends IoHandlerAdapter {@Overridepublic void exceptionCaught(IoSession session, Throwable cause) throws Exception {// TODO Auto-generated method stubsuper.exceptionCaught(session, cause);}@Overridepublic void messageReceived(IoSession session, Object message) throws Exception {System.out.println(message.toString());super.messageReceived(session, message);}@Overridepublic void messageSent(IoSession session, Object message) throws Exception {// TODO Auto-generated method stubsuper.messageSent(session, message);}@Overridepublic void sessionClosed(IoSession session) throws Exception {// TODO Auto-generated method stubsuper.sessionClosed(session);}@Overridepublic void sessionCreated(IoSession session) throws Exception {// TODO Auto-generated method stubsuper.sessionCreated(session);}@Overridepublic void sessionIdle(IoSession session, IdleStatus status) throws Exception {// TODO Auto-generated method stubsuper.sessionIdle(session, status);}/* * (non-Javadoc) * @see org.apache.mina.core.service.IoHandlerAdapter#sessionOpened(org.apache.mina.core.session.IoSession) */@Overridepublic void sessionOpened(IoSession session) throws Exception {// TODO Auto-generated method stubsuper.sessionOpened(session);}}private enum ClientStatus{RUNNING,IDLE,QUIT}private static class KeepAliveMessageFactoryImpl implements KeepAliveMessageFactory { /* * (non-Javadoc) * * @see * org.apache.mina.filter.keepalive.KeepAliveMessageFactory#getRequest * (org.apache.mina.core.session.IoSession) */ @Override public Object getRequest(IoSession session) { // i++; // Log.d("session",i+""); // if (i > 5) { // try { // Log.d("session","睡眠"); // Thread.sleep(40000); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // } return "HRT"; } /* * (non-Javadoc) * * @see * org.apache.mina.filter.keepalive.KeepAliveMessageFactory#getResponse * (org.apache.mina.core.session.IoSession, java.lang.Object) */ @Override public Object getResponse(IoSession session, Object request) { return null; } /* * (non-Javadoc) * * @see * org.apache.mina.filter.keepalive.KeepAliveMessageFactory#isRequest * (org.apache.mina.core.session.IoSession, java.lang.Object) */ @Override public boolean isRequest(IoSession session, Object message) { return false; } /* * (non-Javadoc) * * @see * org.apache.mina.filter.keepalive.KeepAliveMessageFactory#isResponse * (org.apache.mina.core.session.IoSession, java.lang.Object) */ @Override public boolean isResponse(IoSession session, Object message) { /*if (message instanceof HEARTBEATRESPONSE) { // Log.d("session","是响应心跳包"); return true; } */if(message.equals("RES"))return true; return false;} } /*** * @ClassName: KeepAliveRequestTimeoutHandlerImpl * @Description: 当心跳超时时的处理,也可以用默认处理 这里like */ private static class KeepAliveRequestTimeoutHandlerImpl implements KeepAliveRequestTimeoutHandler { /* * (non-Javadoc) * * @seeorg.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler# * keepAliveRequestTimedOut * (org.apache.mina.filter.keepalive.KeepAliveFilter, * org.apache.mina.core.session.IoSession) */ @Override public void keepAliveRequestTimedOut(KeepAliveFilter filter, IoSession session) throws Exception { // ((Logger) LOG).info("心跳超时!"); } } public static void main(String[] args) {// for test TcpClient tcpc = new TcpClient();tcpc.connect(new InetSocketAddress("localhost", 5678), null);}}
问题出在这里
case RUNNING:if(DEBUG) {System.out.println("Connecting...");}// conn = new NioSocketConnector(); ConnectFuture future = conn.connect(inetAddress);// �������� future.awaitUninterruptibly();// �ȴ����Ӵ������ session = future.getSession();// ���session Global.cr.onSessionOk(session);if(DEBUG) {System.out.println("Connected !");}session.getCloseFuture().awaitUninterruptibly();// �ȴ����ӶϿ� if(DEBUG) {System.out.println("Disconnected ~");}session.close(false);// conn.dispose(); break;
当客户端主动或者异常掉线后,此阻塞函数会throw a new exception,之后代码的执行会直接跳进catch里面而不会继续执行未完成的代码。这就造成了NIOConnector一直无法被disposed掉,今儿导致session内部的socket占用的文件描述符无法被释放。
经过我的一番修正,应该是解决了这个问题,具体代码如下:【这里只简单写写核心的代码】
public class TcpClient extends Thread{private final static boolean DEBUG = true;private IoConnector conn = null;private IoSession session = null;private IoHandler handler = null;private ClientStatus clientStatus = ClientStatus.IDLE;private InetSocketAddress inetAddress = null;public TcpClient() {start();}public IoSession getSession() {return session;}@Overridepublic void run() {for(;;) {try {switch (clientStatus) {case IDLE:break;case RUNNING:if(DEBUG) {System.out.println("Connecting...");}// init minaconn = new NioSocketConnector();conn.setConnectTimeoutMillis(1000 * 60); conn.getFilterChain().addLast("codec", new ProtocolCodecFilter(new MessageCodecFactory()));/** 主角登场 */ KeepAliveMessageFactory heartBeatFactory = new KeepAliveMessageFactoryImpl(); KeepAliveFilter heartBeat = new KeepAliveFilter(heartBeatFactory, IdleStatus.BOTH_IDLE); /** 是否回发 */ heartBeat.setForwardEvent(true); /** 发送频率 */ heartBeat.setRequestInterval(15); // connector.getSessionConfig().setKeepAlive(true); conn.getFilterChain().addLast("heartbeat", heartBeat); if(null == handler) {handler = new DefaultClientHandler();}conn.setHandler(handler); ConnectFuture future = conn.connect(inetAddress);// �������� future.awaitUninterruptibly();// �ȴ����Ӵ������ session = future.getSession();// ���session Global.cr.onSessionOk(session);if(DEBUG) {System.out.println("Connected !");}session.getCloseFuture().awaitUninterruptibly();// �ȴ����ӶϿ� if(DEBUG) {System.out.println("Disconnected ~");}break;case QUIT:return ;default:break;}}catch(Exception e) {e.printStackTrace();continue ;} finally {if(null != session)session.close(false);if(null != conn)conn.dispose();try {Thread.sleep(100 * 1);} catch (InterruptedException e) {e.printStackTrace();}}}}/** * * @param inetAddress * @return */public boolean connect(InetSocketAddress inetAddress, IoHandler handler) {this.inetAddress = inetAddress;this.handler = handler;if(clientStatus == ClientStatus.RUNNING) {return false;} else if(clientStatus == ClientStatus.IDLE) {clientStatus = ClientStatus.RUNNING;return true;} else if(clientStatus == ClientStatus.QUIT) {return false;}return true;}@SuppressWarnings("deprecation")public boolean disconnect() {if(clientStatus == ClientStatus.RUNNING) {clientStatus = ClientStatus.IDLE;session.close();return true;}return false;}public boolean send(String msg) {if(null != session && session.isConnected())session.write(msg);return true;}public static class DefaultClientHandler extends IoHandlerAdapter {@Overridepublic void exceptionCaught(IoSession session, Throwable cause) throws Exception {// TODO Auto-generated method stubsuper.exceptionCaught(session, cause);}@Overridepublic void messageReceived(IoSession session, Object message) throws Exception {System.out.println(message.toString());super.messageReceived(session, message);}@Overridepublic void messageSent(IoSession session, Object message) throws Exception {// TODO Auto-generated method stubsuper.messageSent(session, message);}@Overridepublic void sessionClosed(IoSession session) throws Exception {// TODO Auto-generated method stubsuper.sessionClosed(session);}@Overridepublic void sessionCreated(IoSession session) throws Exception {// TODO Auto-generated method stubsuper.sessionCreated(session);}@Overridepublic void sessionIdle(IoSession session, IdleStatus status) throws Exception {// TODO Auto-generated method stubsuper.sessionIdle(session, status);}/* * (non-Javadoc) * @see org.apache.mina.core.service.IoHandlerAdapter#sessionOpened(org.apache.mina.core.session.IoSession) */@Overridepublic void sessionOpened(IoSession session) throws Exception {// TODO Auto-generated method stubsuper.sessionOpened(session);}}private enum ClientStatus{RUNNING,IDLE,QUIT}}
0 0
- Mina框架 open to many file 错误原因以及解决方案
- 关于mina框架里产生too many open files的错误的解决办法
- 虚机打不开报failed to lock the file错误原因及解决方案
- Too many open files 错误解决方案
- 【解决方案】VC++—>add files to folder失效,open-file弹出msdev.exe应用程序错误
- mina高并发短连接导致java.io.IOException: Too many open files解决方案
- mina高并发短连接导致java.io.IOException: Too many open files解决方案
- Ubuntu 报too many open files错误解决方案
- java.io.IOException: Too many open files错误解决方案
- Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法
- Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法
- To many open files
- unable to open database file的原因与解决
- UnsatisfiedLinkError错误的原因以及解决方案
- open一个项目Buliding时间过长的原因以及解决方案:
- Too many arguments to function call错误解决方案
- Unable to open file 'lnk51ew_cc2530b.xcl'的解决方案
- Unable to open file 'lnk51ew_cc2530b.xcl'的解决方案
- TP 框架 常识
- bzoj 2301: [HAOI2011]Problem b (反演)
- 天梯赛决赛题目
- 内部类
- 开源库编译
- Mina框架 open to many file 错误原因以及解决方案
- 关于科研
- MapReduce二次排序(secondary sort)实战
- Python3 requests包学习
- Easyui使用formatter格式化单元格为空解决办法
- 《Java高并发程序设计》学习 --4.3 ThreadLocal
- bzoj 1568 && bzoj 3165 超哥线段树
- Linux中iptables设置详细
- 【POJ2481】cows 线段树